type string;
mandatory true;
}
+ key name;
config:java-name-prefix FileAppenderTO;
}
type string;
mandatory true;
}
+ key name;
leaf file-name-pattern {
type string;
leaf clean-history-on-start {
type boolean;
- default 0;
+ default false;
}
config:java-name-prefix RollingFileAppenderTO;
}
type string;
mandatory true;
}
+ key name;
+
config:java-name-prefix ConsoleAppenderTO;
}
type string;
mandatory true;
}
+ key logger-name;
leaf level {
type string;
for (JavaAttribute ja : rpc.getParameters()) {
Field field = new Field(Collections.<String> emptyList(),
ja.getType().getFullyQualifiedName(),
- ja.getLowerCaseCammelCase());
+ ja.getLowerCaseCammelCase(), ja.getNullableDefaultWrappedForCode());
fields.add(field);
}
MethodDeclaration operation = new MethodDeclaration(
String varName = BindingGeneratorUtil
.parseToValidParamName(attrEntry.getKey());
- String fullyQualifiedName;
+ String fullyQualifiedName, nullableDefault = null;
if (attrEntry.getValue() instanceof TypedAttribute) {
Type type = ((TypedAttribute) attrEntry.getValue()).getType();
fullyQualifiedName = serializeType(type);
+ if(attrEntry.getValue() instanceof JavaAttribute) {
+ nullableDefault = ((JavaAttribute)attrEntry.getValue()).getNullableDefaultWrappedForCode();
+ }
} else {
fullyQualifiedName = FullyQualifiedNameHelper
.getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase());
}
- fields.add(new Field(fullyQualifiedName, varName));
+ fields.add(new Field(fullyQualifiedName, varName, nullableDefault));
String getterName = "get" + innerName;
MethodDefinition getter = new MethodDefinition(
String packageName) {
for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
String type;
+ String nullableDefaultWrapped = null;
AttributeIfc attributeIfc = attrEntry.getValue();
if (attributeIfc instanceof TypedAttribute) {
if (innerAttr instanceof JavaAttribute) {
fullyQualifiedName = ((JavaAttribute) innerAttr)
.getType().getFullyQualifiedName();
+ nullableDefaultWrapped = ((JavaAttribute) innerAttr).getNullableDefaultWrappedForCode();
} else if (innerAttr instanceof TOAttribute) {
fullyQualifiedName = FullyQualifiedNameHelper
.getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
}
fields.add(new Field(type, attributeIfc
- .getUpperCaseCammelCase()));
+ .getUpperCaseCammelCase(), nullableDefaultWrapped));
}
}
void processAttributes(Map<String, AttributeIfc> attributes,
String packageName) {
for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
- String type;
+ String type, nullableDefaultWrapped = null;
AttributeIfc attributeIfc = attrEntry.getValue();
if (attributeIfc instanceof TypedAttribute) {
TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
type = serializeType(typedAttribute.getType());
+ if (attributeIfc instanceof JavaAttribute) {
+ nullableDefaultWrapped = ((JavaAttribute) attributeIfc).getNullableDefaultWrappedForCode();
+ }
+
} else if (attributeIfc instanceof TOAttribute) {
String fullyQualifiedName = FullyQualifiedNameHelper
.getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
if (innerAttr instanceof JavaAttribute) {
fullyQualifiedName = ((JavaAttribute) innerAttr)
.getType().getFullyQualifiedName();
+ nullableDefaultWrapped = ((JavaAttribute) innerAttr).getNullableDefaultWrappedForCode();
} else if (innerAttr instanceof TOAttribute) {
fullyQualifiedName = FullyQualifiedNameHelper
.getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
String varName = BindingGeneratorUtil
.parseToValidParamName(attrEntry.getKey());
moduleFields.add(new ModuleField(type, varName, attributeIfc
- .getUpperCaseCammelCase(), attributeIfc
- .getNullableDefault(), isDependency, dependency));
+ .getUpperCaseCammelCase(), nullableDefaultWrapped, isDependency, dependency));
String getterName = "get"
+ attributeIfc.getUpperCaseCammelCase();
*/
package org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model;
-import java.util.List;
-
import com.google.common.collect.Lists;
+import java.util.List;
+
public class Field {
private final String type;
private final String name;
this(Lists.<String> newArrayList(), type, name, null);
}
+ public Field(String type, String name, String definition) {
+ this(Lists.<String> newArrayList(), type, name, definition);
+ }
+
public Field(List<String> modifiers, String type, String name) {
this(modifiers, type, name, null);
}
assertDeclaredField(fieldDeclarations,
"private java.util.concurrent.ThreadFactory threadfactoryDependency");
assertDeclaredField(fieldDeclarations,
- "private java.lang.Long keepAlive=10");
+ "private java.lang.Long keepAlive=new java.lang.Long(\"10\")");
assertDeclaredField(fieldDeclarations,
"private java.lang.Long coreSize");
assertDeclaredField(fieldDeclarations, "private byte[] binary");
*/
package org.opendaylight.controller.config.yangjmxgenerator.plugin;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-import java.util.Collections;
-import java.util.Map;
-
+import com.google.common.collect.Maps;
import org.junit.Test;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
-import com.google.common.collect.Maps;
+import java.util.Collections;
+import java.util.Map;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
public class ModuleMXBeanEntryTemplatesTest {
doReturn("package.type").when(typeA).getFullyQualifiedName();
doReturn(typeA).when(attr).getType();
doReturn("Type").when(attr).getUpperCaseCammelCase();
+ doReturn("new Default()").when(attr).getNullableDefault();
return attr;
}
*/
package org.opendaylight.controller.config.yangjmxgenerator;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
/**
* Represents part of yang model that describes a module.
}
/**
- * @return services implemented by this module. Keys are fully qualified java names of generated
- * ServiceInterface classes, values are identity local names.
+ * @return services implemented by this module. Keys are fully qualified
+ * java names of generated ServiceInterface classes, values are
+ * identity local names.
*/
public Map<String, QName> getProvidedServices() {
return providedServices;
e.getConflictingName(), when.getQName(),
when.getQName());
}
-
checkUniqueRuntimeBeansGeneratedClasses(
uniqueGeneratedClassesNames, when, runtimeBeans);
Set<RuntimeBeanEntry> runtimeBeanEntryValues = Sets
.<RuntimeBeanEntry> emptyList());
}
}
+ // check attributes name uniqueness
+ for (Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
+ checkUniqueRuntimeBeanAttributesName(entry.getValue(),
+ uniqueGeneratedClassesNames);
+ }
if (unaugmentedModuleIdentities.size() > 0) {
logger.warn("Augmentation not found for all module identities: {}",
unaugmentedModuleIdentities.keySet());
}
}
+ private static void checkUniqueRuntimeBeanAttributesName(
+ ModuleMXBeanEntry mxBeanEntry,
+ Map<String, QName> uniqueGeneratedClassesNames) {
+ for (RuntimeBeanEntry runtimeBeanEntry : mxBeanEntry.getRuntimeBeans()) {
+ for (String runtimeAttName : runtimeBeanEntry
+ .getYangPropertiesToTypesMap().keySet()) {
+ if (mxBeanEntry.getAttributes().keySet()
+ .contains(runtimeAttName)) {
+ QName qName1 = uniqueGeneratedClassesNames
+ .get(runtimeBeanEntry.getJavaNameOfRuntimeMXBean());
+ QName qName2 = uniqueGeneratedClassesNames.get(mxBeanEntry
+ .getGloballyUniqueName());
+ throw new NameConflictException(runtimeAttName, qName1,
+ qName2);
+ }
+ }
+ }
+ }
+
private static void checkUniqueAttributesWithGeneratedClass(
Map<String, QName> uniqueGeneratedClassNames, QName parentQName,
Map<String, AttributeIfc> yangToAttributes) {
private static AttributeIfc getAttributeValue(DataSchemaNode attrNode,
Module currentModule,
Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
- TypeProviderWrapper typeProviderWrapper, SchemaContext schemaContext, String packageName) {
+ TypeProviderWrapper typeProviderWrapper,
+ SchemaContext schemaContext, String packageName) {
if (attrNode instanceof LeafSchemaNode) {
// simple type
} else if (attrNode instanceof ContainerSchemaNode) {
// reference or TO
ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode;
- Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(containerSchemaNode,
- attrNode, currentModule, qNamesToSIEs, schemaContext);
+ Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
+ containerSchemaNode, attrNode, currentModule, qNamesToSIEs,
+ schemaContext);
if (dependencyAttributeOptional.isPresent()) {
return dependencyAttributeOptional.get();
} else {
- return TOAttribute.create(containerSchemaNode, typeProviderWrapper, packageName);
+ return TOAttribute.create(containerSchemaNode,
+ typeProviderWrapper, packageName);
}
} else if (attrNode instanceof LeafListSchemaNode) {
typeProviderWrapper);
} else if (attrNode instanceof ListSchemaNode) {
ListSchemaNode listSchemaNode = (ListSchemaNode) attrNode;
- Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(listSchemaNode,
- attrNode, currentModule, qNamesToSIEs, schemaContext);
+ Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
+ listSchemaNode, attrNode, currentModule, qNamesToSIEs,
+ schemaContext);
if (dependencyAttributeOptional.isPresent()) {
return dependencyAttributeOptional.get();
} else {
- return ListAttribute.create(listSchemaNode, typeProviderWrapper, packageName);
+ return ListAttribute.create(listSchemaNode,
+ typeProviderWrapper, packageName);
}
} else {
throw new UnsupportedOperationException(
}
}
- private static Optional<? extends AbstractDependencyAttribute> extractDependency(DataNodeContainer dataNodeContainer,
- DataSchemaNode attrNode,
- Module currentModule,
- Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
- SchemaContext schemaContext) {
+ private static Optional<? extends AbstractDependencyAttribute> extractDependency(
+ DataNodeContainer dataNodeContainer, DataSchemaNode attrNode,
+ Module currentModule,
+ Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
+ SchemaContext schemaContext) {
if (dataNodeContainer.getUses().size() == 1
&& getChildNodeSizeWithoutUses(dataNodeContainer) == 0) {
// reference
- UsesNode usesNode = dataNodeContainer.getUses().iterator()
- .next();
+ UsesNode usesNode = dataNodeContainer.getUses().iterator().next();
checkState(usesNode.getRefines().size() == 1,
"Unexpected 'refine' child node size of "
+ dataNodeContainer);
.values().iterator().next();
checkState(refine.getUnknownSchemaNodes().size() == 1,
"Unexpected unknown schema node size of " + refine);
- UnknownSchemaNode requiredIdentity = refine
- .getUnknownSchemaNodes().iterator().next();
+ UnknownSchemaNode requiredIdentity = refine.getUnknownSchemaNodes()
+ .iterator().next();
checkState(
ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity
- .getNodeType()),
- "Unexpected language extension " + requiredIdentity);
+ .getNodeType()), "Unexpected language extension "
+ + requiredIdentity);
String prefixAndIdentityLocalName = requiredIdentity
.getNodeParameter();
// import should point to a module
ServiceInterfaceEntry serviceInterfaceEntry = findSIE(
- prefixAndIdentityLocalName, currentModule,
- qNamesToSIEs, schemaContext);
+ prefixAndIdentityLocalName, currentModule, qNamesToSIEs,
+ schemaContext);
boolean mandatory = refine.getConstraints().isMandatory();
AbstractDependencyAttribute reference;
- if (dataNodeContainer instanceof ContainerSchemaNode ){
- reference = new DependencyAttribute(attrNode, serviceInterfaceEntry,
- mandatory, attrNode.getDescription());
+ if (dataNodeContainer instanceof ContainerSchemaNode) {
+ reference = new DependencyAttribute(attrNode,
+ serviceInterfaceEntry, mandatory,
+ attrNode.getDescription());
} else {
- reference = new ListDependenciesAttribute(attrNode, serviceInterfaceEntry,
- mandatory, attrNode.getDescription());
+ reference = new ListDependenciesAttribute(attrNode,
+ serviceInterfaceEntry, mandatory,
+ attrNode.getDescription());
}
return Optional.of(reference);
}
return getType(leaf, type);
}
+ public String getDefault(LeafSchemaNode node) {
+ return typeProvider.getTypeDefaultConstruction(node);
+ }
+
public Type getType(SchemaNode leaf, TypeDefinition<?> type) {
Type javaType;
try {
public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
private final Type type;
- private final String nullableDescription, nullableDefault;
+ private final String nullableDescription, nullableDefault, nullableDefaultWrappedForCode;
private final TypeProviderWrapper typeProviderWrapper;
private final TypeDefinition<?> typeDefinition;
this.typeDefinition = leaf.getType();
this.typeProviderWrapper = typeProviderWrapper;
this.nullableDefault = leaf.getDefault();
+ this.nullableDefaultWrappedForCode = leaf.getDefault() == null ? null : typeProviderWrapper.getDefault(leaf);
this.nullableDescription = leaf.getDescription();
}
this.type = typeProviderWrapper.getType(leaf);
this.typeDefinition = leaf.getType();
this.typeProviderWrapper = typeProviderWrapper;
- this.nullableDefault = null;
+ this.nullableDefault = nullableDefaultWrappedForCode = null;
this.nullableDescription = leaf.getDescription();
}
+ public TypeDefinition<?> getTypeDefinition() {
+ return typeDefinition;
+ }
+
/**
* Returns the most base type
*/
return baseType;
}
+ public String getNullableDefaultWrappedForCode() {
+ return nullableDefaultWrappedForCode;
+ }
+
@Override
public Type getType() {
return type;
testedYangModulesToExpectedConflictingName.put(
"config-test-runtime-bean-name-conflict2",
"StateARuntimeMXBean");
+ testedYangModulesToExpectedConflictingName.put(
+ "config-test-duplicate-attribute-in-runtime-and-mxbean",
+ "port");
}
private String getYangModuleName(String name) {
--- /dev/null
+// vi: set smarttab et sw=4 tabstop=4:
+module config-test-duplicate-attribute-in-runtime-and-mxbean {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:jmx:duplicate:runtime";
+ prefix "th-java";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+ import ietf-inet-types { prefix inet; revision-date 2010-09-24;}
+
+
+ description
+ "This module contains the base YANG definitions for NS-OS
+ thread services pure Java implementation.";
+
+ revision "2013-04-05" {
+ description
+ "Updated to work with new anchors.";
+ }
+
+ revision "2013-04-03" {
+ description
+ "Initial revision.";
+ }
+
+ identity async-eventbus {
+ base config:module-type;
+ config:java-name-prefix AsyncEventBus;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case async-eventbus {
+ when "/config:modules/config:module/config:type = 'async-eventbus'";
+ leaf port {
+ type string;
+ }
+ leaf core-size {
+ type uint32;
+ }
+ leaf simple-int3 {
+ type uint16;
+ }
+ }
+ }
+
+ augment "/config:modules/config:module/config:state" {
+ case async-eventbus {
+ when "/config:modules/config:module/config:type = 'async-eventbus'";
+ leaf simple-arg {
+ type uint32;
+ }
+ leaf port {
+ type inet:port-number;
+ }
+ }
+ }
+}
\ No newline at end of file
container dto-a {
leaf simple-arg {
type uint32;
+ default 1;
}
leaf port {
type inet:port-number;
+ default 8080;
}
+ leaf ip4 {
+ type inet:ipv4-address;
+ default 127.0.0.1;
+ }
+
+ leaf ip {
+ type inet:ip-address;
+ // TODO defaults for union default 0:0:0:0:0:0:0:1;
+ }
}
leaf as-number {
- mandatory true;
type inet:as-number;
+ default 44;
}
leaf simpleInt {
type uint32;
- default 99L;
+ default 99;
}
container dto_b {
leaf simple-int1 {
type uint32;
+ default 32;
}
leaf simple-int2 {
when "/config:modules/config:module/config:type = 'impl-netconf'";
leaf binaryLeaf {
type binary;
+ default ZGVmYXVsdEJpbg==;
}
leaf type {
type string;
+ default "default-string";
}
leaf extended {
type tt:extend-once;
+ default 1;
}
leaf extended-twice {
type tt:extend-twice;
+ default 2;
}
leaf extended-enum {
type tt:extend-enum;
+ default ONE;
}
leaf sleep-factor {
type decimal64 {
fraction-digits 2;
}
+ default 2.00;
}
container dto-c {
}
leaf simple-long {
- type int64 ;
+ type int64;
+ default -45;
}
leaf simple-long-2 {
type uint32;
+ default 445;
}
leaf simple-BigInteger {
type uint64;
+ default 545454;
}
leaf simple-byte {
type int8;
+ default -4;
}
leaf simple-short {
type uint8;
+ default 45;
}
leaf simple-test {
container deep {
leaf simple-int3 {
type uint16;
+ default 0;
}
}
}
container retValContainer {
leaf v1 {
type string;
+ default "from rpc";
}
leaf v2 {
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>ganymed</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-remoterpc-connector</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>
+ zeromq-routingtable.implementation
+ </artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.zeromq</groupId>
+ <artifactId>jeromq</artifactId>
+ <version>0.3.1</version>
+ </dependency>
</dependencies>
</profile>
<profile>
<type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-threadgroup</type>
<instance>
<name>global-boss-group</name>
- <provider>/config/modules/module[name='netty-threadgroup-fixed']/instance[name='global-boss-group']</provider>
+ <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-boss-group']</provider>
</instance>
<instance>
<name>global-worker-group</name>
- <provider>/config/modules/module[name='netty-threadgroup-fixed']/instance[name='global-worker-group']</provider>
+ <provider>/modules/module[type='netty-threadgroup-fixed'][name='global-worker-group']</provider>
</instance>
</service>
<service>
<type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-event-executor</type>
<instance>
<name>global-event-executor</name>
- <provider>/config/modules/module[name='netty-global-event-executor']/instance[name='global-event-executor']</provider>
+ <provider>/modules/module[type='netty-global-event-executor'][name='global-event-executor']</provider>
</instance>
</service>
<service>
<type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-timer</type>
<instance>
<name>global-timer</name>
- <provider>/config/modules/module[name='netty-hashed-wheel-timer']/instance[name='global-timer']</provider>
+ <provider>/modules/module[type='netty-hashed-wheel-timer'][name='global-timer']</provider>
</instance>
</service>
//CAPABILITIES START
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
<instance>
<name>ref_yang-schema-service</name>
- <provider>/config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']</provider>
+ <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
</instance>
</service>
<service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
<instance>
<name>ref_binding-notification-broker</name>
- <provider>/config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']</provider>
+ <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
</instance>
</service>
<service>
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
<instance>
<name>ref_hash-map-data-store</name>
- <provider>/config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']</provider>
+ <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
</instance>
<instance>
- <name>ref_cluster-data-store</name>
- <provider>/config/modules/module[name='dom-clustered-store-impl']/instance[name='cluster-data-store']</provider>
- </instance>
+ <name>ref_cluster-data-store</name>
+ <provider>/modules/module[type='dom-clustered-store-impl'][name='cluster-data-store']</provider>
+ </instance>
</service>
<service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
<instance>
<name>ref_binding-broker-impl</name>
- <provider>/config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']</provider>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
</instance>
</service>
<service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
<instance>
- <name>ref_binding-rpc-broker</name>
- <provider>/config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']</provider>
+ <name>binding-rpc-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
</instance>
</service>
<service>
<type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
<instance>
<name>ref_runtime-mapping-singleton</name>
- <provider>/config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']</provider>
+ <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
</instance>
</service>
<service>
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
<instance>
<name>ref_dom-broker</name>
- <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']</provider>
+ <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
</instance>
</service>
<service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
<instance>
<name>ref_binding-data-broker</name>
- <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
+ <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
</instance>
</service>
//CAPABILITIES START
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsInputBuilder
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionBuilder
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionBuilder
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder
import java.util.Collections
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.controller.action._case.ControllerActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.action._case.FloodActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.all.action._case.FloodAllActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.hw.path.action._case.HwPathActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.loopback.action._case.LoopbackActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.type.action._case.SetDlTypeActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.next.hop.action._case.SetNextHopActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.tos.action._case.SetNwTosActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.dst.action._case.SetTpDstActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.src.action._case.SetTpSrcActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.cfi.action._case.SetVlanCfiActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.pcp.action._case.SetVlanPcpActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.sw.path.action._case.SwPathActionBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCaseBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder
public class MDFlowMapping {
public static def Instructions toApplyInstruction(ArrayList<Action> actions) {
val it = new InstructionsBuilder;
val applyActions = new InstructionBuilder;
- applyActions.instruction = new ApplyActionsBuilder().setAction(actions).build()
+ applyActions.instruction = new ApplyActionsCaseBuilder().setApplyActions(new ApplyActionsBuilder().setAction(actions).build()).build()
instruction = Collections.<Instruction>singletonList(applyActions.build)
return it.build;
}
public static dispatch def toAction(Controller sourceAction) {
val actionBuilder = new ActionBuilder();
- actionBuilder.action = new ControllerActionBuilder().build();
+ actionBuilder.action = new ControllerActionCaseBuilder().setControllerAction(new ControllerActionBuilder().build()).build();
return actionBuilder.build();
}
public static dispatch def toAction(Drop sourceAction) {
val actionBuilder = new ActionBuilder();
- actionBuilder.action = new DropActionBuilder().build();
+ actionBuilder.action = new DropActionCaseBuilder().setDropAction(new DropActionBuilder().build()).build();
return actionBuilder.build();
}
public static dispatch def toAction(Flood sourceAction) {
val actionBuilder = new ActionBuilder();
- actionBuilder.action = new FloodActionBuilder().build();
+ actionBuilder.action = new FloodActionCaseBuilder().setFloodAction(new FloodActionBuilder().build).build();
return actionBuilder.build();
}
public static dispatch def toAction(FloodAll sourceAction) {
val actionBuilder = new ActionBuilder();
- actionBuilder.action = new FloodAllActionBuilder().build();
+ actionBuilder.action = new FloodAllActionCaseBuilder().setFloodAllAction(new FloodAllActionBuilder().build()).build();
return actionBuilder.build();
}
public static dispatch def toAction(HwPath sourceAction) {
val actionBuilder = new ActionBuilder();
- actionBuilder.action = new HwPathActionBuilder().build();
+ actionBuilder.action = new HwPathActionCaseBuilder().setHwPathAction(new HwPathActionBuilder().build()).build();
return actionBuilder.build();
}
public static dispatch def toAction(Loopback sourceAction) {
val actionBuilder = new ActionBuilder();
- actionBuilder.action = new LoopbackActionBuilder().build();
+ actionBuilder.action = new LoopbackActionCaseBuilder().setLoopbackAction(new LoopbackActionBuilder().build()).build();
return actionBuilder.build();
}
val actionBuilder = new ActionBuilder();
val it = new OutputActionBuilder();
outputNodeConnector = sourceAction.port.toUri;
- actionBuilder.action = it.build();
+ actionBuilder.action = new OutputActionCaseBuilder().setOutputAction(it.build()).build();
return actionBuilder.build();
}
public static dispatch def toAction(PopVlan sourceAction) {
val actionBuilder = new ActionBuilder();
- actionBuilder.action = new PopVlanActionBuilder().build();
+ actionBuilder.action = new PopVlanActionCaseBuilder().build();
return actionBuilder.build();
}
vlanId = new VlanId(sourceAction.vlanId);
pcp = sourceAction.pcp;
tag = sourceAction.tag;
- actionBuilder.action = it.build();
+ actionBuilder.action = new PushVlanActionCaseBuilder().setPushVlanAction(it.build()).build();
return actionBuilder.build();
}
val actionBuilder = new ActionBuilder();
val it = new SetDlDstActionBuilder();
address = sourceAction.dlAddress.toMacAddress();
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetDlDstActionCaseBuilder().setSetDlDstAction(it.build()).build;
return actionBuilder.build();
}
val actionBuilder = new ActionBuilder();
val it = new SetDlSrcActionBuilder();
address = sourceAction.dlAddress.toMacAddress;
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetDlSrcActionCaseBuilder().setSetDlSrcAction(it.build()).build;
return actionBuilder.build();
}
val actionBuilder = new ActionBuilder();
val it = new SetDlTypeActionBuilder();
dlType = new EtherType(sourceAction.dlType as long);
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetDlTypeActionCaseBuilder().setSetDlTypeAction(it.build()).build();
return actionBuilder.build();
}
val it = new SetNextHopActionBuilder();
val inetAddress = sourceAction.address;
address = inetAddress.toInetAddress;
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetNextHopActionCaseBuilder().setSetNextHopAction(it.build).build();
return actionBuilder.build();
}
val it = new SetNwDstActionBuilder();
val inetAddress = sourceAction.address;
address = inetAddress.toInetAddress;
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetNwDstActionCaseBuilder().setSetNwDstAction(it.build()).build();
return actionBuilder.build();
}
val it = new SetNwSrcActionBuilder();
val inetAddress = sourceAction.address;
address = inetAddress.toInetAddress;
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetNwSrcActionCaseBuilder().setSetNwSrcAction(it.build()).build();
return actionBuilder.build();
}
val actionBuilder = new ActionBuilder();
val it = new SetNwTosActionBuilder();
tos = sourceAction.nwTos;
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetNwTosActionCaseBuilder().setSetNwTosAction(it.build).build;
return actionBuilder.build();
}
val actionBuilder = new ActionBuilder();
val it = new SetTpDstActionBuilder();
port = new PortNumber(sourceAction.port);
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetTpDstActionCaseBuilder().setSetTpDstAction(it.build()).build();
return actionBuilder.build();
}
val actionBuilder = new ActionBuilder();
val it = new SetTpSrcActionBuilder();
port = new PortNumber(sourceAction.port);
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetTpSrcActionCaseBuilder().setSetTpSrcAction(it.build()).build();
return actionBuilder.build();
}
val actionBuilder = new ActionBuilder();
val it = new SetVlanCfiActionBuilder();
vlanCfi = new VlanCfi(sourceAction.cfi);
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetVlanCfiActionCaseBuilder().setSetVlanCfiAction(it.build()).build();
return actionBuilder.build();
}
val it = new SetVlanIdActionBuilder();
vlanId = new VlanId(sourceAction.vlanId);
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetVlanIdActionCaseBuilder().setSetVlanIdAction(it.build()).build();
return actionBuilder.build();
}
val actionBuilder = new ActionBuilder();
val it = new SetVlanPcpActionBuilder();
vlanPcp = new VlanPcp(sourceAction.pcp as short);
- actionBuilder.action = it.build();
+ actionBuilder.action = new SetVlanPcpActionCaseBuilder().setSetVlanPcpAction(it.build).build;
return actionBuilder.build();
}
public static dispatch def toAction(SwPath sourceAction) {
val actionBuilder = new ActionBuilder();
- actionBuilder.action = new SwPathActionBuilder().build();
+ actionBuilder.action = new SwPathActionCaseBuilder().setSwPathAction(new SwPathActionBuilder().build()).build();
return actionBuilder.build();
}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.ActionList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetMplsTtlAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTtlAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetMplsTtlActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTtlActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow source) {
if (source.getInstructions() != null) {
for (Instruction instruction : source.getInstructions().getInstruction()) {
- if (instruction.getInstruction() instanceof ActionList) {
- return (((ActionList) instruction.getInstruction()).getAction());
+ if (instruction.getInstruction() instanceof ApplyActionsCase) {
+ return (((ApplyActionsCase) instruction.getInstruction()).getApplyActions().getAction());
}
}
}
org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action sourceAction = action
.getAction();
- if (sourceAction instanceof ControllerAction) {
+ if (sourceAction instanceof ControllerActionCase) {
targetAction.add(new Controller());
- } else if (sourceAction instanceof OutputAction) {
+ } else if (sourceAction instanceof OutputActionCase) {
- Uri nodeConnector = ((OutputAction) sourceAction).getOutputNodeConnector();
+ Uri nodeConnector = ((OutputActionCase) sourceAction).getOutputAction().getOutputNodeConnector();
if (nodeConnector != null) {
//for (Uri uri : nodeConnectors) {
targetAction.add(new Output(fromNodeConnectorRef(nodeConnector)));
//}
}
- } else if (sourceAction instanceof PopMplsAction) {
+ } else if (sourceAction instanceof PopMplsActionCase) {
// TODO: define maping
- } else if (sourceAction instanceof PushMplsAction) {
+ } else if (sourceAction instanceof PushMplsActionCase) {
// TODO: define maping
- } else if (sourceAction instanceof PushPbbAction) {
+ } else if (sourceAction instanceof PushPbbActionCase) {
// TODO: define maping
- } else if (sourceAction instanceof SetMplsTtlAction) {
+ } else if (sourceAction instanceof SetMplsTtlActionCase) {
// TODO: define maping
// targetAction = //no action to map
- } else if (sourceAction instanceof SetNwTtlAction) {
+ } else if (sourceAction instanceof SetNwTtlActionCase) {
// TODO: define maping
- } else if (sourceAction instanceof SetQueueAction) {
+ } else if (sourceAction instanceof SetQueueActionCase) {
// TODO: define maping
// targetAction = //no action to map
- } else if (sourceAction instanceof DropAction) {
+ } else if (sourceAction instanceof DropActionCase) {
targetAction.add(new Drop());
- } else if (sourceAction instanceof FloodAction) {
+ } else if (sourceAction instanceof FloodActionCase) {
targetAction.add(new Flood());
- } else if (sourceAction instanceof FloodAllAction) {
+ } else if (sourceAction instanceof FloodAllActionCase) {
targetAction.add(new FloodAll());
- } else if (sourceAction instanceof HwPathAction) {
+ } else if (sourceAction instanceof HwPathActionCase) {
targetAction.add(new HwPath());
- } else if (sourceAction instanceof LoopbackAction) {
+ } else if (sourceAction instanceof LoopbackActionCase) {
targetAction.add(new Loopback());
- } else if (sourceAction instanceof PopVlanAction) {
+ } else if (sourceAction instanceof PopVlanActionCase) {
targetAction.add(new PopVlan());
- } else if (sourceAction instanceof PushVlanAction) {
- PushVlanAction pushVlanAction = (PushVlanAction) sourceAction;
- PushVlan pushVlan = pushVlanFrom(pushVlanAction);
+ } else if (sourceAction instanceof PushVlanActionCase) {
+ PushVlanActionCase pushVlanAction = (PushVlanActionCase) sourceAction;
+ PushVlan pushVlan = pushVlanFrom(pushVlanAction.getPushVlanAction());
if (pushVlan != null) {
targetAction.add(pushVlan);
}
- } else if (sourceAction instanceof SetDlDstAction) {
- MacAddress addressL2Dest = ((SetDlDstAction) sourceAction).getAddress();
+ } else if (sourceAction instanceof SetDlDstActionCase) {
+ MacAddress addressL2Dest = ((SetDlDstActionCase) sourceAction).getSetDlDstAction().getAddress();
if (addressL2Dest != null) {
targetAction.add(new SetDlDst(bytesFrom(addressL2Dest)));
}
- } else if (sourceAction instanceof SetDlSrcAction) {
- MacAddress addressL2Src = ((SetDlSrcAction) sourceAction).getAddress();
+ } else if (sourceAction instanceof SetDlSrcActionCase) {
+ MacAddress addressL2Src = ((SetDlSrcActionCase) sourceAction).getSetDlSrcAction().getAddress();
if (addressL2Src != null) {
targetAction.add(new SetDlSrc(bytesFrom(addressL2Src)));
}
- } else if (sourceAction instanceof SetDlTypeAction) {
- EtherType dlType = ((SetDlTypeAction) sourceAction).getDlType();
+ } else if (sourceAction instanceof SetDlTypeActionCase) {
+ EtherType dlType = ((SetDlTypeActionCase) sourceAction).getSetDlTypeAction().getDlType();
if (dlType != null) {
Long dlTypeValue = dlType.getValue();
if (dlTypeValue != null) {
targetAction.add(new SetDlType(dlTypeValue.intValue()));
}
}
- } else if (sourceAction instanceof SetNextHopAction) {
- Address addressL3 = ((SetNextHopAction) sourceAction).getAddress();
+ } else if (sourceAction instanceof SetNextHopActionCase) {
+ Address addressL3 = ((SetNextHopActionCase) sourceAction).getSetNextHopAction().getAddress();
InetAddress inetAddress = inetAddressFrom(addressL3);
if (inetAddress != null) {
targetAction.add(new SetNextHop(inetAddress));
}
- } else if (sourceAction instanceof SetNwDstAction) {
- Address addressL3 = ((SetNwDstAction) sourceAction).getAddress();
+ } else if (sourceAction instanceof SetNwDstActionCase) {
+ Address addressL3 = ((SetNwDstActionCase) sourceAction).getSetNwDstAction().getAddress();
InetAddress inetAddress = inetAddressFrom(addressL3);
if (inetAddress != null) {
targetAction.add(new SetNwDst(inetAddress));
}
- } else if (sourceAction instanceof SetNwSrcAction) {
- Address addressL3 = ((SetNwSrcAction) sourceAction).getAddress();
+ } else if (sourceAction instanceof SetNwSrcActionCase) {
+ Address addressL3 = ((SetNwSrcActionCase) sourceAction).getSetNwSrcAction().getAddress();
InetAddress inetAddress = inetAddressFrom(addressL3);
if (inetAddress != null) {
targetAction.add(new SetNwSrc(inetAddress));
}
- } else if (sourceAction instanceof SetNwTosAction) {
- Integer tos = ((SetNwTosAction) sourceAction).getTos();
+ } else if (sourceAction instanceof SetNwTosActionCase) {
+ Integer tos = ((SetNwTosActionCase) sourceAction).getSetNwTosAction().getTos();
if (tos != null) {
targetAction.add(new SetNwTos(tos));
}
- } else if (sourceAction instanceof SetTpDstAction) {
- PortNumber port = ((SetTpDstAction) sourceAction).getPort();
+ } else if (sourceAction instanceof SetTpDstActionCase) {
+ PortNumber port = ((SetTpDstActionCase) sourceAction).getSetTpDstAction().getPort();
if (port != null) {
Integer portValue = port.getValue();
if (port.getValue() != null) {
targetAction.add(new SetTpDst(portValue));
}
}
- } else if (sourceAction instanceof SetTpSrcAction) {
- PortNumber port = ((SetTpSrcAction) sourceAction).getPort();
+ } else if (sourceAction instanceof SetTpSrcActionCase) {
+ PortNumber port = ((SetTpSrcActionCase) sourceAction).getSetTpSrcAction().getPort();
if (port != null) {
Integer portValue = port.getValue();
if (port.getValue() != null) {
targetAction.add(new SetTpSrc(portValue));
}
}
- } else if (sourceAction instanceof SetVlanCfiAction) {
- VlanCfi vlanCfi = ((SetVlanCfiAction) sourceAction).getVlanCfi();
+ } else if (sourceAction instanceof SetVlanCfiActionCase) {
+ VlanCfi vlanCfi = ((SetVlanCfiActionCase) sourceAction).getSetVlanCfiAction().getVlanCfi();
if (vlanCfi != null) {
Integer vlanCfiValue = vlanCfi.getValue();
if (vlanCfiValue != null) {
targetAction.add(new SetVlanCfi(vlanCfiValue));
}
}
- } else if (sourceAction instanceof SetVlanIdAction) {
- org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId vlanID = ((SetVlanIdAction) sourceAction)
+ } else if (sourceAction instanceof SetVlanIdActionCase) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId vlanID = ((SetVlanIdActionCase) sourceAction).getSetVlanIdAction()
.getVlanId();
if (vlanID != null) {
Integer vlanIdValue = vlanID.getValue();
targetAction.add(new SetVlanId(vlanIdValue));
}
}
- } else if (sourceAction instanceof SetVlanPcpAction) {
- VlanPcp vlanPcp = ((SetVlanPcpAction) sourceAction).getVlanPcp();
+ } else if (sourceAction instanceof SetVlanPcpActionCase) {
+ VlanPcp vlanPcp = ((SetVlanPcpActionCase) sourceAction).getSetVlanPcpAction().getVlanPcp();
if (vlanPcp != null) {
Short vlanPcpValue = vlanPcp.getValue();
if (vlanPcpValue != null) {
targetAction.add(new SetVlanPcp(vlanPcpValue));
}
}
- } else if (sourceAction instanceof SwPathAction) {
+ } else if (sourceAction instanceof SwPathActionCase) {
targetAction.add(new SwPath());
}
}
return null;
}
- private static PushVlan pushVlanFrom(PushVlanAction pushVlanAction) {
+ private static PushVlan pushVlanFrom(org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanAction pushVlanAction) {
final int tag;
final int pcp;
final int cfi;
import org.opendaylight.controller.sal.match.MatchType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanAction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
private void checkOdActions(
List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions) {
- checkOdAction(actions, FloodAction.class, false);
- checkOdAction(actions, FloodAllAction.class, false);
- checkOdAction(actions, HwPathAction.class, false);
- checkOdAction(actions, LoopbackAction.class, false);
- checkOdAction(actions, PopVlanAction.class, false);
- checkOdAction(actions, PushVlanAction.class, true);
- checkOdAction(actions, SetDlDstAction.class, true);
- checkOdAction(actions, SetDlSrcAction.class, true);
- checkOdAction(actions, SetDlTypeAction.class, true);
- checkOdAction(actions, SetNwTosAction.class, true);
- checkOdAction(actions, SetNwDstAction.class, true);
- checkOdAction(actions, SetNwSrcAction.class, true);
- checkOdAction(actions, SetNextHopAction.class, true);
- checkOdAction(actions, SetTpDstAction.class, true);
- checkOdAction(actions, SetTpSrcAction.class, true);
- checkOdAction(actions, SetVlanCfiAction.class, true);
- checkOdAction(actions, SetVlanIdAction.class, true);
- checkOdAction(actions, SetVlanPcpAction.class, true);
- checkOdAction(actions, SwPathAction.class, false);
+ checkOdAction(actions, FloodActionCase.class, false);
+ checkOdAction(actions, FloodAllActionCase.class, false);
+ checkOdAction(actions, HwPathActionCase.class, false);
+ checkOdAction(actions, LoopbackActionCase.class, false);
+ checkOdAction(actions, PopVlanActionCase.class, false);
+ checkOdAction(actions, PushVlanActionCase.class, true);
+ checkOdAction(actions, SetDlDstActionCase.class, true);
+ checkOdAction(actions, SetDlSrcActionCase.class, true);
+ checkOdAction(actions, SetDlTypeActionCase.class, true);
+ checkOdAction(actions, SetNwTosActionCase.class, true);
+ checkOdAction(actions, SetNwDstActionCase.class, true);
+ checkOdAction(actions, SetNwSrcActionCase.class, true);
+ checkOdAction(actions, SetNextHopActionCase.class, true);
+ checkOdAction(actions, SetTpDstActionCase.class, true);
+ checkOdAction(actions, SetTpSrcActionCase.class, true);
+ checkOdAction(actions, SetVlanCfiActionCase.class, true);
+ checkOdAction(actions, SetVlanIdActionCase.class, true);
+ checkOdAction(actions, SetVlanPcpActionCase.class, true);
+ checkOdAction(actions, SwPathActionCase.class, false);
}
private void checkOdAction(
.getAction();
if (cl.isInstance(innerAction)) {
numOfFoundActions++;
- if (innerAction instanceof PushVlanAction) {
- assertEquals("Wrong value of cfi in PushVlanAction.", (Integer) 1, ((PushVlanAction) innerAction)
+ if (innerAction instanceof PushVlanActionCase) {
+ assertEquals("Wrong value of cfi in PushVlanAction.", (Integer) 1, ((PushVlanActionCase) innerAction).getPushVlanAction()
.getCfi().getValue());
assertEquals("Wrong value of pcp in PushVlanAction.", (Integer) 7,
- ((PushVlanAction) innerAction).getPcp());
+ ((PushVlanActionCase) innerAction).getPushVlanAction().getPcp());
assertEquals("Wrong value of tag in PushVlanAction.", (Integer) 0x8100,
- ((PushVlanAction) innerAction).getTag());
+ ((PushVlanActionCase) innerAction).getPushVlanAction().getTag());
assertEquals("Wrong value of vlad ID in PushVlanAction.", (Integer) 4095,
- ((PushVlanAction) innerAction).getVlanId().getValue());
- } else if (innerAction instanceof SetDlDstAction) {
+ ((PushVlanActionCase) innerAction).getPushVlanAction().getVlanId().getValue());
+ } else if (innerAction instanceof SetDlDstActionCase) {
assertEquals("Wrong MAC destination address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
- ((SetDlDstAction) innerAction).getAddress().getValue());
- } else if (innerAction instanceof SetDlSrcAction) {
+ ((SetDlDstActionCase) innerAction).getSetDlDstAction().getAddress().getValue());
+ } else if (innerAction instanceof SetDlSrcActionCase) {
assertEquals("Wrong MAC source address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
- ((SetDlSrcAction) innerAction).getAddress().getValue());
- } else if (innerAction instanceof SetDlTypeAction) {
+ ((SetDlSrcActionCase) innerAction).getSetDlSrcAction().getAddress().getValue());
+ } else if (innerAction instanceof SetDlTypeActionCase) {
assertEquals("Wrong data link type in SetDlTypeAction.", (long) 513,
- (long) ((SetDlTypeAction) innerAction).getDlType().getValue());
- } else if (innerAction instanceof SetNextHopAction) {
- Address address = ((SetNextHopAction) innerAction).getAddress();
+ (long) ((SetDlTypeActionCase) innerAction).getSetDlTypeAction().getDlType().getValue());
+ } else if (innerAction instanceof SetNextHopActionCase) {
+ Address address = ((SetNextHopActionCase) innerAction).getSetNextHopAction().getAddress();
boolean ipv4AddressFound = false;
if (address instanceof Ipv4) {
ipv4AddressFound = true;
.getIpv4Address().getValue());
}
assertTrue("Ipv4 address wasn't found.", ipv4AddressFound);
- } else if (innerAction instanceof SetNwTosAction) {
- assertEquals("Wrong TOS in SetNwTosAction.", (Integer) 63, ((SetNwTosAction) innerAction).getTos());
- } else if (innerAction instanceof SetNwDstAction) {
- Address address = ((SetNwDstAction) innerAction).getAddress();
+ } else if (innerAction instanceof SetNwTosActionCase) {
+ assertEquals("Wrong TOS in SetNwTosAction.", (Integer) 63, ((SetNwTosActionCase) innerAction).getSetNwTosAction().getTos());
+ } else if (innerAction instanceof SetNwDstActionCase) {
+ Address address = ((SetNwDstActionCase) innerAction).getSetNwDstAction().getAddress();
boolean ipv4AddressFound = false;
if (address instanceof Ipv4) {
ipv4AddressFound = true;
.getIpv4Address().getValue());
}
assertTrue("Ipv4 address wasn't found.", ipv4AddressFound);
- } else if (innerAction instanceof SetNwSrcAction) {
- Address address = ((SetNwSrcAction) innerAction).getAddress();
+ } else if (innerAction instanceof SetNwSrcActionCase) {
+ Address address = ((SetNwSrcActionCase) innerAction).getSetNwSrcAction().getAddress();
boolean ipv4AddressFound = false;
if (address instanceof Ipv4) {
ipv4AddressFound = true;
.getIpv4Address().getValue());
}
assertTrue("Ipv4 address wasn't found.", ipv4AddressFound);
- } else if (innerAction instanceof SetTpDstAction) {
+ } else if (innerAction instanceof SetTpDstActionCase) {
assertEquals("Port number is incorrect in SetTpDstAction.", (Integer) 65534,
- ((SetTpDstAction) innerAction).getPort().getValue());
- } else if (innerAction instanceof SetTpSrcAction) {
+ ((SetTpDstActionCase) innerAction).getSetTpDstAction().getPort().getValue());
+ } else if (innerAction instanceof SetTpSrcActionCase) {
assertEquals("Port number is incorrect in SetTpSrcAction.", (Integer) 65535,
- ((SetTpSrcAction) innerAction).getPort().getValue());
- } else if (innerAction instanceof SetVlanCfiAction) {
+ ((SetTpSrcActionCase) innerAction).getSetTpSrcAction().getPort().getValue());
+ } else if (innerAction instanceof SetVlanCfiActionCase) {
assertEquals("Vlan cfi number is incorrect in SetVlanCfiAction.", (Integer) 1,
- ((SetVlanCfiAction) innerAction).getVlanCfi().getValue());
- } else if (innerAction instanceof SetVlanIdAction) {
+ ((SetVlanCfiActionCase) innerAction).getSetVlanCfiAction().getVlanCfi().getValue());
+ } else if (innerAction instanceof SetVlanIdActionCase) {
assertEquals("Vlan id number is incorrect in SetVlanIdAction.", (Integer) 4095,
- ((SetVlanIdAction) innerAction).getVlanId().getValue());
- } else if (innerAction instanceof SetVlanPcpAction) {
+ ((SetVlanIdActionCase) innerAction).getSetVlanIdAction().getVlanId().getValue());
+ } else if (innerAction instanceof SetVlanPcpActionCase) {
assertEquals("Vlan pcp number is incorrect in SetVlanPcpAction.", new Short((short) 7),
- ((SetVlanPcpAction) innerAction).getVlanPcp().getValue());
+ ((SetVlanPcpActionCase) innerAction).getSetVlanPcpAction().getVlanPcp().getValue());
}
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.VlanCfi;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.controller.action._case.ControllerActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.action._case.FloodActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.flood.all.action._case.FloodAllActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.hw.path.action._case.HwPathActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.loopback.action._case.LoopbackActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.mpls.action._case.PushMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.pbb.action._case.PushPbbActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.type.action._case.SetDlTypeActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.mpls.ttl.action._case.SetMplsTtlActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.next.hop.action._case.SetNextHopActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.tos.action._case.SetNwTosActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.ttl.action._case.SetNwTtlActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.queue.action._case.SetQueueActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.dst.action._case.SetTpDstActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.src.action._case.SetTpSrcActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.cfi.action._case.SetVlanCfiActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.pcp.action._case.SetVlanPcpActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.sw.path.action._case.SwPathActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
import com.google.common.net.InetAddresses;
private Instructions prepareOdActions() {
List<Action> odActions = new ArrayList<>();
- ControllerActionBuilder controllerActionBuilder = new ControllerActionBuilder();
- DropActionBuilder dropActionBuilder = new DropActionBuilder();
- FloodActionBuilder floodActionBuilder = new FloodActionBuilder();
- FloodAllActionBuilder floodAllActionBuilder = new FloodAllActionBuilder();
- HwPathActionBuilder hwPathActionBuilder = new HwPathActionBuilder();
- LoopbackActionBuilder loopbackActionBuilder = new LoopbackActionBuilder();
- OutputActionBuilder outputActionBuilder = new OutputActionBuilder();
- PopMplsActionBuilder popMplsActionBuilder = new PopMplsActionBuilder();
- PopVlanActionBuilder popVlanActionBuilder = new PopVlanActionBuilder();
- PushMplsActionBuilder pushMplsActionBuilder = new PushMplsActionBuilder();
- PushPbbActionBuilder pushPbbActionBuilder = new PushPbbActionBuilder();
- PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
- SetDlDstActionBuilder setDlDstActionBuilder = new SetDlDstActionBuilder();
- SetDlSrcActionBuilder setDlSrcActionBuilder = new SetDlSrcActionBuilder();
- SetDlTypeActionBuilder setDlTypeActionBuilder = new SetDlTypeActionBuilder();
- SetMplsTtlActionBuilder setMplsTtlActionBuilder = new SetMplsTtlActionBuilder();
- SetNwTosActionBuilder setNwTosActionBuilder = new SetNwTosActionBuilder();
- SetNwTtlActionBuilder setNwTtlActionBuilder = new SetNwTtlActionBuilder();
- SetQueueActionBuilder setQueueActionBuilder = new SetQueueActionBuilder();
- SetTpDstActionBuilder setTpDstActionBuilder = new SetTpDstActionBuilder();
- SetTpSrcActionBuilder setTpSrcActionBuilder = new SetTpSrcActionBuilder();
- SetVlanCfiActionBuilder setVlanCfiActionBuilder = new SetVlanCfiActionBuilder();
- SetVlanIdActionBuilder setVlanIdActionBuilder = new SetVlanIdActionBuilder();
- SetVlanPcpActionBuilder setVlanPcpActionBuilder = new SetVlanPcpActionBuilder();
- SwPathActionBuilder swPathActionBuilder = new SwPathActionBuilder();
+ ControllerActionCaseBuilder controllerActionBuilder = new ControllerActionCaseBuilder();
+ DropActionCaseBuilder dropActionBuilder = new DropActionCaseBuilder();
+ FloodActionCaseBuilder floodActionBuilder = new FloodActionCaseBuilder();
+ FloodAllActionCaseBuilder floodAllActionBuilder = new FloodAllActionCaseBuilder();
+ HwPathActionCaseBuilder hwPathActionBuilder = new HwPathActionCaseBuilder();
+ LoopbackActionCaseBuilder loopbackActionBuilder = new LoopbackActionCaseBuilder();
+ OutputActionCaseBuilder outputActionBuilder = new OutputActionCaseBuilder();
+ PopMplsActionCaseBuilder popMplsActionBuilder = new PopMplsActionCaseBuilder();
+ PopVlanActionCaseBuilder popVlanActionBuilder = new PopVlanActionCaseBuilder();
+ PushMplsActionCaseBuilder pushMplsActionBuilder = new PushMplsActionCaseBuilder();
+ PushPbbActionCaseBuilder pushPbbActionBuilder = new PushPbbActionCaseBuilder();
+ PushVlanActionCaseBuilder pushVlanActionBuilder = new PushVlanActionCaseBuilder();
+ SetDlDstActionCaseBuilder setDlDstActionBuilder = new SetDlDstActionCaseBuilder();
+ SetDlSrcActionCaseBuilder setDlSrcActionBuilder = new SetDlSrcActionCaseBuilder();
+ SetDlTypeActionCaseBuilder setDlTypeActionBuilder = new SetDlTypeActionCaseBuilder();
+ SetMplsTtlActionCaseBuilder setMplsTtlActionBuilder = new SetMplsTtlActionCaseBuilder();
+ SetNwTosActionCaseBuilder setNwTosActionBuilder = new SetNwTosActionCaseBuilder();
+ SetNwTtlActionCaseBuilder setNwTtlActionBuilder = new SetNwTtlActionCaseBuilder();
+ SetQueueActionCaseBuilder setQueueActionBuilder = new SetQueueActionCaseBuilder();
+ SetTpDstActionCaseBuilder setTpDstActionBuilder = new SetTpDstActionCaseBuilder();
+ SetTpSrcActionCaseBuilder setTpSrcActionBuilder = new SetTpSrcActionCaseBuilder();
+ SetVlanCfiActionCaseBuilder setVlanCfiActionBuilder = new SetVlanCfiActionCaseBuilder();
+ SetVlanIdActionCaseBuilder setVlanIdActionBuilder = new SetVlanIdActionCaseBuilder();
+ SetVlanPcpActionCaseBuilder setVlanPcpActionBuilder = new SetVlanPcpActionCaseBuilder();
+ SwPathActionCaseBuilder swPathActionBuilder = new SwPathActionCaseBuilder();
prepareActionOutput(outputActionBuilder);
prepareActionPushVlan(pushVlanActionBuilder);
odActions.add(new ActionBuilder().setAction(swPathActionBuilder.build()).build());
- ApplyActions innerInst = new ApplyActionsBuilder().setAction(odActions).build();
+ ApplyActionsCase innerInst = new ApplyActionsCaseBuilder().setApplyActions(new ApplyActionsBuilder().setAction(odActions).build()).build();
Instruction applyActions = new InstructionBuilder().setInstruction(innerInst).build();
List<Instruction> instructions = Collections.singletonList(applyActions );
InstructionsBuilder instBuilder = new InstructionsBuilder();
return instBuilder.build();
}
- private void prepareActionSetVlanPcp(SetVlanPcpActionBuilder setVlanPcpActionBuilder) {
+ private void prepareActionSetVlanPcp(SetVlanPcpActionCaseBuilder wrapper) {
+ SetVlanPcpActionBuilder setVlanPcpActionBuilder = new SetVlanPcpActionBuilder();
setVlanPcpActionBuilder.setVlanPcp(new VlanPcp((short) 7));
+ wrapper.setSetVlanPcpAction(setVlanPcpActionBuilder.build());
}
- private void prepareActionSetVladId(SetVlanIdActionBuilder setVlanIdActionBuilder) {
+ private void prepareActionSetVladId(SetVlanIdActionCaseBuilder wrapper) {
+ SetVlanIdActionBuilder setVlanIdActionBuilder = new SetVlanIdActionBuilder();
setVlanIdActionBuilder.setVlanId(new VlanId(4095));
+ wrapper.setSetVlanIdAction(setVlanIdActionBuilder.build());
}
- private void prepareActionSetVlanCfi(SetVlanCfiActionBuilder setVlanCfiActionBuilder) {
+ private void prepareActionSetVlanCfi(SetVlanCfiActionCaseBuilder wrapper) {
+ SetVlanCfiActionBuilder setVlanCfiActionBuilder = new SetVlanCfiActionBuilder();
setVlanCfiActionBuilder.setVlanCfi(new VlanCfi(1));
+ wrapper.setSetVlanCfiAction(setVlanCfiActionBuilder.build());
}
- private void prepareActionSetTpDst(SetTpDstActionBuilder setTpDstActionBuilder) {
+ private void prepareActionSetTpDst(SetTpDstActionCaseBuilder wrapper) {
+ SetTpDstActionBuilder setTpDstActionBuilder = new SetTpDstActionBuilder();
setTpDstActionBuilder.setPort(new PortNumber(65535));
+ wrapper.setSetTpDstAction(setTpDstActionBuilder.build());
}
- private void prepareActionSetTpSrc(SetTpSrcActionBuilder setTpSrcActionBuilder) {
+ private void prepareActionSetTpSrc(SetTpSrcActionCaseBuilder wrapper) {
+ SetTpSrcActionBuilder setTpSrcActionBuilder = new SetTpSrcActionBuilder();
setTpSrcActionBuilder.setPort(new PortNumber(65535));
+ wrapper.setSetTpSrcAction(setTpSrcActionBuilder.build());
}
- private void prepareActionSetNwTos(SetNwTosActionBuilder setNwTosActionBuilder) {
+ private void prepareActionSetNwTos(SetNwTosActionCaseBuilder wrapper) {
+ SetNwTosActionBuilder setNwTosActionBuilder = new SetNwTosActionBuilder();
setNwTosActionBuilder.setTos(63);
+ wrapper.setSetNwTosAction(setNwTosActionBuilder.build());
}
private void prepareActionSetNwSrc(List<Action> odActions) {
// test case for IPv4
SetNwSrcActionBuilder setNwSrcActionBuilderIpv4 = new SetNwSrcActionBuilder();
setNwSrcActionBuilderIpv4.setAddress(prapareIpv4Address("192.168.100.102"));
- odActions.add(new ActionBuilder().setAction(setNwSrcActionBuilderIpv4.build()).build());
+ odActions.add(new ActionBuilder().setAction(new SetNwSrcActionCaseBuilder().setSetNwSrcAction(setNwSrcActionBuilderIpv4.build()).build()).build());
// test case for IPv6
SetNwSrcActionBuilder setNwSrcActionBuilderIpv6 = new SetNwSrcActionBuilder();
setNwSrcActionBuilderIpv6.setAddress(prapareIpv6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7336"));
- odActions.add(new ActionBuilder().setAction(setNwSrcActionBuilderIpv6.build()).build());
+ odActions.add(new ActionBuilder().setAction(new SetNwSrcActionCaseBuilder().setSetNwSrcAction(setNwSrcActionBuilderIpv6.build()).build()).build());
}
private void prepareActionSetNwDst(List<Action> odActions) {
// test case for IPv4
+
SetNwDstActionBuilder setNwDstActionBuilderIpv4 = new SetNwDstActionBuilder();
setNwDstActionBuilderIpv4.setAddress(prapareIpv4Address("192.168.100.101"));
- odActions.add(new ActionBuilder().setAction(setNwDstActionBuilderIpv4.build()).build());
+ odActions.add(new ActionBuilder().setAction(new SetNwDstActionCaseBuilder().setSetNwDstAction(setNwDstActionBuilderIpv4.build()).build()).build());
// test case for IPv6
SetNwDstActionBuilder setNwDstActionBuilderIpv6 = new SetNwDstActionBuilder();
setNwDstActionBuilderIpv6.setAddress(prapareIpv6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7335"));
- odActions.add(new ActionBuilder().setAction(setNwDstActionBuilderIpv6.build()).build());
+ odActions.add(new ActionBuilder().setAction(new SetNwDstActionCaseBuilder().setSetNwDstAction(setNwDstActionBuilderIpv6.build()).build()).build());
}
private void prepareActionNextHop(List<Action> odActions) {
// test case for IPv4
SetNextHopActionBuilder setNextHopActionBuilderIpv4 = new SetNextHopActionBuilder();
setNextHopActionBuilderIpv4.setAddress(prapareIpv4Address("192.168.100.100"));
- odActions.add(new ActionBuilder().setAction(setNextHopActionBuilderIpv4.build()).build());
+ odActions.add(new ActionBuilder().setAction(new SetNextHopActionCaseBuilder().setSetNextHopAction(setNextHopActionBuilderIpv4.build()).build()).build());
// test case for IPv6
SetNextHopActionBuilder setNextHopActionBuilderIpv6 = new SetNextHopActionBuilder();
setNextHopActionBuilderIpv6.setAddress(prapareIpv6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7334"));
- odActions.add(new ActionBuilder().setAction(setNextHopActionBuilderIpv6.build()).build());
+ odActions.add(new ActionBuilder().setAction(new SetNextHopActionCaseBuilder().setSetNextHopAction(setNextHopActionBuilderIpv6.build()).build()).build());
}
private Address prapareIpv4Address(String ipv4Address) {
return ipv6Builder.build();
}
- private void prepareActionSetDlType(SetDlTypeActionBuilder setDlTypeActionBuilder) {
+ private void prepareActionSetDlType(SetDlTypeActionCaseBuilder wrapper) {
+ SetDlTypeActionBuilder setDlTypeActionBuilder = new SetDlTypeActionBuilder();
setDlTypeActionBuilder.setDlType(new EtherType(513l));
+ wrapper.setSetDlTypeAction(setDlTypeActionBuilder.build());
}
- private void prepareActionSetDlSrc(SetDlSrcActionBuilder setDlSrcActionBuilder) {
+ private void prepareActionSetDlSrc(SetDlSrcActionCaseBuilder wrapper) {
+ SetDlSrcActionBuilder setDlSrcActionBuilder = new SetDlSrcActionBuilder();
setDlSrcActionBuilder.setAddress(new MacAddress("24:77:03:7C:C5:F1"));
+ wrapper.setSetDlSrcAction(setDlSrcActionBuilder.build());
}
- private void prepareActionSetDlDst(SetDlDstActionBuilder setDlDstActionBuilder) {
+ private void prepareActionSetDlDst(SetDlDstActionCaseBuilder wrapper) {
+ SetDlDstActionBuilder setDlDstActionBuilder = new SetDlDstActionBuilder();
setDlDstActionBuilder.setAddress(new MacAddress("3C:A9:F4:00:E0:C8"));
+ wrapper.setSetDlDstAction(setDlDstActionBuilder.build());
}
- private void prepareActionPushVlan(PushVlanActionBuilder pushVlanActionBuilder) {
+ private void prepareActionPushVlan(PushVlanActionCaseBuilder wrapper) {
+ PushVlanActionBuilder pushVlanActionBuilder = new PushVlanActionBuilder();
pushVlanActionBuilder.setPcp(7); // 3 bits
pushVlanActionBuilder.setCfi(new VlanCfi(1)); // 1 bit
pushVlanActionBuilder.setVlanId(new VlanId(4095));
pushVlanActionBuilder.setTag(0x8100); // 12 bit
+ wrapper.setPushVlanAction(pushVlanActionBuilder.build());
}
- private void prepareActionOutput(OutputActionBuilder outputActionBuilder) {
+ private void prepareActionOutput(OutputActionCaseBuilder wrapper) {
+ OutputActionBuilder outputActionBuilder = new OutputActionBuilder();
outputActionBuilder.setOutputNodeConnector(new Uri("uri1"));
+ wrapper.setOutputAction(outputActionBuilder.build());
}
private Match prepOdMatch(MtchType mt) {
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Bundle-Activator>org.opendaylight.controller.forwardingrulesmanager.consumer.impl.FRMConsumerImpl</Bundle-Activator>
+ <Bundle-Activator>org.opendaylight.controller.frm.FRMActivator</Bundle-Activator>
</instructions>
</configuration>
</plugin>
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTable;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.Meter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
public class FRMUtil {
protected static final Logger logger = LoggerFactory.getLogger(FRMUtil.class);
for (Action curaction : actions) {
org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action = curaction
.getAction();
- if (action instanceof ControllerAction) {
- Integer length = ((ControllerAction) action).getMaxLength();
+ if (action instanceof ControllerActionCase) {
+ Integer length = ((ControllerActionCase) action).getControllerAction().getMaxLength();
if (length < 0 || length > 65294) {
logger.error("Controller: MaxLength is not valid");
return false;
}
- } else if (action instanceof OutputAction) {
- Integer length = ((OutputAction) action).getMaxLength();
- Uri outputnodeconnector = ((OutputAction) action).getOutputNodeConnector();
+ } else if (action instanceof OutputActionCase) {
+ Integer length = ((OutputActionCase) action).getOutputAction().getMaxLength();
+ Uri outputnodeconnector = ((OutputActionCase) action).getOutputAction().getOutputNodeConnector();
if (length < 0 || length > 65294) {
logger.error("OutputAction: MaxLength is not valid");
return false;
}
}
- } else if (action instanceof PushMplsAction) {
- Integer ethertype = ((PushMplsAction) action).getEthernetType();
+ } else if (action instanceof PushMplsActionCase) {
+ Integer ethertype = ((PushMplsActionCase) action).getPushMplsAction().getEthernetType();
if (ethertype != null && ethertype != 0x8847 && ethertype != 0x8848) {
logger.error("Ether Type is not valid for PushMplsAction");
return false;
}
- } else if (action instanceof PushPbbAction) {
- Integer ethertype = ((PushPbbAction) action).getEthernetType();
+ } else if (action instanceof PushPbbActionCase) {
+ Integer ethertype = ((PushPbbActionCase) action).getPushPbbAction().getEthernetType();
if (ethertype != null && ethertype != 0x88E7) {
logger.error("Ether type is not valid for PushPbbAction");
return false;
}
- } else if (action instanceof PushVlanAction) {
- Integer ethertype = ((PushVlanAction) action).getEthernetType();
+ } else if (action instanceof PushVlanActionCase) {
+ Integer ethertype = ((PushVlanActionCase) action).getPushVlanAction().getEthernetType();
if (ethertype != null && ethertype != 0x8100 && ethertype != 0x88a8) {
logger.error("Ether Type is not valid for PushVlanAction");
return false;
}
- } else if (action instanceof SetDlDstAction) {
- MacAddress address = ((SetDlDstAction) action).getAddress();
- if (address != null && !isL2AddressValid(address.toString())) {
+ } else if (action instanceof SetDlDstActionCase || action instanceof SetDlSrcActionCase) {
+ MacAddress address = ((SetDlDstActionCase) action).getSetDlDstAction().getAddress();
+ if (address != null && !isL2AddressValid(address.getValue())) {
logger.error("SetDlDstAction: Address not valid");
return false;
}
- } else if (action instanceof SetDlSrcAction) {
- MacAddress address = ((SetDlSrcAction) action).getAddress();
- if (address != null && !isL2AddressValid(address.toString())) {
+ } else if (action instanceof SetDlSrcActionCase) {
+ MacAddress address = ((SetDlSrcActionCase) action).getSetDlSrcAction().getAddress();
+ if (address != null && !isL2AddressValid(address.getValue())) {
logger.error("SetDlSrcAction: Address not valid");
return false;
}
- } else if (action instanceof SetQueueAction) {
- String queue = ((SetQueueAction) action).getQueue();
+ } else if (action instanceof SetQueueActionCase) {
+ String queue = ((SetQueueActionCase) action).getSetQueueAction().getQueue();
if (queue != null && !isQueueValid(queue)) {
logger.error("Queue Id not valid");
return false;
}
- } else if (action instanceof SetTpDstAction) {
- PortNumber port = ((SetTpDstAction) action).getPort();
+ } else if (action instanceof SetTpDstActionCase) {
+ PortNumber port = ((SetTpDstActionCase) action).getSetTpDstAction().getPort();
if (port != null && !isPortValid(port)) {
logger.error("Port not valid");
}
- } else if (action instanceof SetTpSrcAction) {
- PortNumber port = ((SetTpSrcAction) action).getPort();
+ } else if (action instanceof SetTpSrcActionCase) {
+ PortNumber port = ((SetTpSrcActionCase) action).getSetTpSrcAction().getPort();
if (port != null && !isPortValid(port)) {
logger.error("Port not valid");
}
- } else if (action instanceof SetVlanIdAction) {
- VlanId vlanid = ((SetVlanIdAction) action).getVlanId();
- if (vlanid != null && !isVlanIdValid(vlanid.getValue().toString())) {
- logger.error("Vlan ID is not in the range 0 - 4095");
+ } else if (action instanceof SetVlanIdActionCase) {
+ VlanId vlanid = ((SetVlanIdActionCase) action).getSetVlanIdAction().getVlanId();
+ if (vlanid != null && !isVlanIdValid(vlanid.toString())) {
+ logger.error("Vlan ID %s is not in the range 0 - 4095");
return false;
}
- } else if (action instanceof SetVlanPcpAction) {
- VlanPcp vlanpcp = ((SetVlanPcpAction) action).getVlanPcp();
- if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.getValue().toString())) {
- logger.error("Vlan priority is not in the range 0 - 7");
+ } else if (action instanceof SetVlanPcpActionCase) {
+ VlanPcp vlanpcp = ((SetVlanPcpActionCase) action).getSetVlanPcpAction().getVlanPcp();
+ if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.toString())) {
+ logger.error("Vlan priority %s is not in the range 0 - 7");
return false;
}
}
for (Instruction instruction : instructionsList) {
org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
.getInstruction();
- if (curInstruction instanceof GoToTable) {
+ if (curInstruction instanceof GoToTableCase) {
- Short tableid = ((GoToTable) curInstruction).getTableId();
+ Short tableid = ((GoToTableCase) curInstruction).getGoToTable().getTableId();
if (tableid < 0) {
logger.error("table id is not valid");
return false;
}
}
- else if (curInstruction instanceof WriteActions) {
+ else if (curInstruction instanceof WriteActionsCase) {
- List<Action> action = ((WriteActions) curInstruction).getAction();
+ List<Action> action = ((WriteActionsCase) curInstruction).getWriteActions().getAction();
validateActions(action);
}
- else if (curInstruction instanceof ApplyActions) {
- List<Action> action = ((ApplyActions) curInstruction).getAction();
+ else if (curInstruction instanceof ApplyActionsCase) {
+ List<Action> action = ((ApplyActionsCase) curInstruction).getApplyActions().getAction();
validateActions(action);
}
- else if (curInstruction instanceof ClearActions) {
- List<Action> action = ((ClearActions) curInstruction).getAction();
+ else if (curInstruction instanceof ClearActionsCase) {
+ List<Action> action = ((ClearActionsCase) curInstruction).getClearActions().getAction();
validateActions(action);
}
- else if (curInstruction instanceof Meter) {
+ else if (curInstruction instanceof MeterCase) {
- String meter = ((Meter) curInstruction).getMeter();
+ MeterId meter = ((MeterCase) curInstruction).getMeter().getMeterId();
if (meter != null && !isValidMeter(meter)) {
logger.error("Meter Id is not valid");
return false;
return true;
}
- public static boolean isValidMeter(String meter) {
+ public static boolean isValidMeter(MeterId meter) {
// TODO
return true;
}
--- /dev/null
+package org.opendaylight.controller.frm
+
+import java.util.Collections
+import java.util.HashSet
+import java.util.Map.Entry
+import java.util.Set
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.controller.sal.common.util.Rpcs
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.common.RpcError
+
+abstract class AbstractTransaction implements DataCommitTransaction<InstanceIdentifier<?extends DataObject>, DataObject> {
+
+ @Property
+ val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+
+ new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ _modification = modification;
+ }
+
+ def void validate() throws IllegalStateException
+
+ override finish() throws IllegalStateException {
+ validate()
+ callRpcs();
+ return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
+ }
+
+ override getModification() {
+ return _modification;
+ }
+
+ override rollback() throws IllegalStateException {
+ rollbackRpcs();
+ return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
+ }
+
+ def private callRpcs() {
+ val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet();
+
+ /*
+ * This little dance is because updatedEntries contains both created and modified entries
+ * The reason I created a new HashSet is because the collections we are returned are immutable.
+ */
+ val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
+ updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet());
+ updatedEntries.removeAll(createdEntries);
+
+ val Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData();
+ for (Entry<InstanceIdentifier<? extends DataObject >, DataObject> entry : createdEntries) {
+ add(entry.key,entry.value);
+ }
+ for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
+ val originalFlow = _modification.originalConfigurationData.get(entry.key);
+ val updatedFlow = entry.value
+ update(entry.key, originalFlow ,updatedFlow);
+ }
+
+ for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
+ val removeValue = _modification.getOriginalConfigurationData.get(instanceId);
+ remove(instanceId,removeValue);
+ }
+ }
+
+ def void remove(InstanceIdentifier<?> identifier, DataObject remove)
+
+ def void update(InstanceIdentifier<?> identifier, DataObject original, DataObject update)
+
+ def void add(InstanceIdentifier<?> identifier, DataObject add)
+
+ def private rollbackRpcs() {
+ val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet();
+
+ /*
+ * This little dance is because updatedEntries contains both created and modified entries
+ * The reason I created a new HashSet is because the collections we are returned are immutable.
+ */
+ val Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<? extends DataObject>, DataObject>>();
+ updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet());
+ updatedEntries.removeAll(createdEntries);
+
+ val Set<InstanceIdentifier<? >> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData();
+ for (Entry<InstanceIdentifier<?>, DataObject> entry : createdEntries) {
+ remove(entry.key,entry.value); // because we are rolling back, remove what we would have added.
+ }
+ for (Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
+ val originalFlow = _modification.originalConfigurationData.get(entry.key);
+ val updatedFlow = entry.value
+ update(entry.key, updatedFlow ,originalFlow);// because we are rolling back, replace the updated with the original
+ }
+
+ for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
+ val removeValue = _modification.getOriginalConfigurationData.get(instanceId);
+ add(instanceId,removeValue);// because we are rolling back, add what we would have removed.
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.frm
+
+import org.opendaylight.controller.frm.flow.FlowProvider
+import org.opendaylight.controller.frm.group.GroupProvider
+import org.opendaylight.controller.frm.meter.MeterProvider
+import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
+import org.osgi.framework.BundleContext
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
+
+class FRMActivator extends AbstractBindingAwareProvider {
+
+ static var FlowProvider provider = new FlowProvider();
+ static var GroupProvider groupProvider = new GroupProvider();
+ static var MeterProvider meterProvider = new MeterProvider();
+
+ override onSessionInitiated(ProviderContext session) {
+ provider.dataService = session.getSALService(DataProviderService)
+ provider.salFlowService = session.getRpcService(SalFlowService);
+ provider.start();
+
+ groupProvider.dataService = session.getSALService(DataProviderService)
+ groupProvider.salGroupService = session.getRpcService(SalGroupService)
+ groupProvider.start();
+
+ meterProvider.dataService = session.getSALService(DataProviderService)
+ meterProvider.salMeterService = session.getRpcService(SalMeterService)
+ meterProvider.start();
+ }
+
+ override protected stopImpl(BundleContext context) {
+ provider.close();
+ groupProvider.close();
+ meterProvider.close();
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.frm.flow
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+
+class FlowCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ @Property
+ val SalFlowService salFlowService;
+
+ new(SalFlowService manager) {
+ _salFlowService = manager;
+ }
+
+ override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ return new FlowTransaction(modification,salFlowService);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.frm.flow
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yangtools.concepts.Registration
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.slf4j.LoggerFactory
+
+class FlowProvider implements AutoCloseable {
+
+ @Property
+ DataProviderService dataService;
+
+ @Property
+ SalFlowService salFlowService;
+
+ FlowCommitHandler commitHandler
+
+ Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
+
+ static val LOG = LoggerFactory.getLogger(FlowProvider);
+
+ def void start() {
+ commitHandler = new FlowCommitHandler(salFlowService)
+ val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
+ .child(Node)
+ .augmentation(FlowCapableNode)
+ .child(Table)
+ .child(Flow)
+ .toInstance();
+ commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
+ LOG.info("Flow Config Provider started.");
+ }
+
+ protected def startChange() {
+ return dataService.beginTransaction;
+ }
+
+ override close() throws Exception {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.frm.flow
+
+import org.opendaylight.controller.frm.AbstractTransaction
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+
+class FlowTransaction extends AbstractTransaction {
+
+ @Property
+ val SalFlowService salFlowService;
+
+ new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalFlowService salFlowService) {
+ super(modification)
+ _salFlowService = salFlowService;
+ }
+
+ override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
+ if(obj instanceof Flow) {
+ val flow = (obj as Flow)
+ val tableInstanceId = instanceId.firstIdentifierOf(Table);
+ val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+ val builder = new RemoveFlowInputBuilder(flow);
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setFlowTable(new FlowTableRef(tableInstanceId));
+ _salFlowService.removeFlow(builder.build());
+ }
+ }
+
+ override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
+ if(originalObj instanceof Flow && updatedObj instanceof Flow) {
+ val originalFlow = (originalObj as Flow)
+ val updatedFlow = (updatedObj as Flow)
+ val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+ val builder = new UpdateFlowInputBuilder();
+ builder.setNode(new NodeRef(nodeInstanceId));
+ val ufb = new UpdatedFlowBuilder(updatedFlow);
+ builder.setUpdatedFlow((ufb.build()));
+ val ofb = new OriginalFlowBuilder(originalFlow);
+ builder.setOriginalFlow(ofb.build());
+ _salFlowService.updateFlow(builder.build());
+
+ }
+ }
+
+ override add(InstanceIdentifier<?> instanceId, DataObject obj) {
+ if(obj instanceof Flow) {
+ val flow = (obj as Flow)
+ val tableInstanceId = instanceId.firstIdentifierOf(Table);
+ val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+ val builder = new AddFlowInputBuilder(flow);
+ builder.setNode(new NodeRef(nodeInstanceId));
+ builder.setFlowTable(new FlowTableRef(tableInstanceId));
+ _salFlowService.addFlow(builder.build());
+ }
+ }
+
+ override validate() throws IllegalStateException {
+ FlowTransactionValidator.validate(this)
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.frm.flow;
+
+public class FlowTransactionValidator {
+
+ public static void validate(FlowTransaction transaction) throws IllegalStateException {
+ // NOOP
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.frm.group
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+
+class GroupCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ @Property
+ val SalGroupService groupService;
+
+ new(SalGroupService groupService) {
+ _groupService = groupService;
+ }
+
+ override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ return new GroupTransaction(modification,groupService);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.frm.group
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yangtools.concepts.Registration
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.slf4j.LoggerFactory
+
+class GroupProvider implements AutoCloseable {
+
+ @Property
+ DataProviderService dataService;
+
+ @Property
+ SalGroupService salGroupService;
+
+ GroupCommitHandler commitHandler
+
+ Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
+
+ static val LOG = LoggerFactory.getLogger(GroupProvider);
+
+ def void start() {
+ commitHandler = new GroupCommitHandler(salGroupService)
+ val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
+ .child(Node)
+ .augmentation(FlowCapableNode)
+ .child(Group)
+ .toInstance();
+ commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
+ LOG.info("Group Config Provider started.");
+ }
+
+ protected def startChange() {
+ return dataService.beginTransaction;
+ }
+
+ override close() throws Exception {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.frm.group
+
+import org.opendaylight.controller.frm.AbstractTransaction
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder
+
+class GroupTransaction extends AbstractTransaction {
+
+ @Property
+ val SalGroupService groupService;
+
+ new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalGroupService groupService) {
+ super(modification)
+ _groupService = groupService;
+ }
+
+ override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
+ if(obj instanceof Group) {
+ val group = (obj as Group)
+ val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+ val builder = new RemoveGroupInputBuilder(group);
+ builder.setNode(new NodeRef(nodeInstanceId));
+ _groupService.removeGroup(builder.build());
+ }
+ }
+
+ override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
+ if(originalObj instanceof Group && updatedObj instanceof Group) {
+ val originalGroup = (originalObj as Group)
+ val updatedGroup = (updatedObj as Group)
+ val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+ val builder = new UpdateGroupInputBuilder();
+ builder.setNode(new NodeRef(nodeInstanceId));
+ val ufb = new UpdatedGroupBuilder(updatedGroup);
+ builder.setUpdatedGroup((ufb.build()));
+ val ofb = new OriginalGroupBuilder(originalGroup);
+ builder.setOriginalGroup(ofb.build());
+ _groupService.updateGroup(builder.build());
+
+ }
+ }
+
+ override add(InstanceIdentifier<?> instanceId, DataObject obj) {
+ if(obj instanceof Group) {
+ val group = (obj as Group)
+ val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+ val builder = new AddGroupInputBuilder(group);
+ builder.setNode(new NodeRef(nodeInstanceId));
+ _groupService.addGroup(builder.build());
+ }
+ }
+
+ override validate() throws IllegalStateException {
+ GroupTransactionValidator.validate(this)
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.frm.group;
+
+public class GroupTransactionValidator {
+
+ public static void validate(GroupTransaction transaction) throws IllegalStateException {
+ // NOOP
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.frm.meter
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+
+class FlowCommitHandler implements DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ @Property
+ val SalMeterService salMeterService;
+
+ new(SalMeterService manager) {
+ _salMeterService = manager;
+ }
+
+ override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ return new MeterTransaction(modification,salMeterService);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.frm.meter
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
+import org.opendaylight.yangtools.concepts.Registration
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.slf4j.LoggerFactory
+
+class MeterProvider implements AutoCloseable {
+
+ @Property
+ DataProviderService dataService;
+
+ @Property
+ SalMeterService salMeterService;
+
+ FlowCommitHandler commitHandler
+
+ Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject>> commitHandlerRegistration;
+
+ static val LOG = LoggerFactory.getLogger(MeterProvider);
+
+ def void start() {
+ commitHandler = new FlowCommitHandler(salMeterService)
+ val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Nodes)
+ .child(Node)
+ .augmentation(FlowCapableNode)
+ .child(Meter)
+ .toInstance();
+ commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler);
+ LOG.info("Meter Config Provider started.");
+ }
+
+ protected def startChange() {
+ return dataService.beginTransaction;
+ }
+
+ override close() throws Exception {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.frm.meter
+
+import org.opendaylight.controller.frm.AbstractTransaction
+import org.opendaylight.controller.md.sal.common.api.data.DataModification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+
+class MeterTransaction extends AbstractTransaction {
+
+ @Property
+ val SalMeterService salMeterService;
+
+ new(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,SalMeterService salMeterService) {
+ super(modification)
+ _salMeterService = salMeterService;
+ }
+
+ override remove(InstanceIdentifier<?> instanceId, DataObject obj) {
+ if(obj instanceof Meter) {
+ val meter = (obj as Meter)
+ val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+ val builder = new RemoveMeterInputBuilder(meter);
+ builder.setNode(new NodeRef(nodeInstanceId));
+ _salMeterService.removeMeter(builder.build());
+ }
+ }
+
+ override update(InstanceIdentifier<?> instanceId, DataObject originalObj, DataObject updatedObj) {
+ if(originalObj instanceof Meter && updatedObj instanceof Meter) {
+ val originalMeter = (originalObj as Meter)
+ val updatedMeter = (updatedObj as Meter)
+ val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+ val builder = new UpdateMeterInputBuilder();
+ builder.setNode(new NodeRef(nodeInstanceId));
+ val ufb = new UpdatedMeterBuilder(updatedMeter);
+ builder.setUpdatedMeter((ufb.build()));
+ val ofb = new OriginalMeterBuilder(originalMeter);
+ builder.setOriginalMeter(ofb.build());
+ _salMeterService.updateMeter(builder.build());
+
+ }
+ }
+
+ override add(InstanceIdentifier<?> instanceId, DataObject obj) {
+ if(obj instanceof Meter) {
+ val meter = (obj as Meter)
+ val nodeInstanceId = instanceId.firstIdentifierOf(Node);
+ val builder = new AddMeterInputBuilder(meter);
+ builder.setNode(new NodeRef(nodeInstanceId));
+ _salMeterService.addMeter(builder.build());
+ }
+ }
+
+ override validate() throws IllegalStateException {
+ MeterTransactionValidator.validate(this)
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.frm.meter;
+
+public class MeterTransactionValidator {
+
+ public static void validate(MeterTransaction transaction) throws IllegalStateException {
+ // NOOP
+ }
+
+}
+++ /dev/null
-module opendaylight-action-types {
- namespace "urn:opendaylight:action:types";
- prefix action;
-
- import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
- import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
- import opendaylight-l2-types {prefix l2t; revision-date "2013-08-27";}
- import opendaylight-match-types {prefix match; revision-date "2013-10-26";}
-
- revision "2013-11-12" {
- description "Initial revision of action service";
- }
-
- typedef vlan-cfi {
- type int32;
- }
-
- grouping address {
- choice address {
- case ipv4 {
- leaf ipv4-address {
- type inet:ipv4-prefix;
- }
- }
- case ipv6 {
- leaf ipv6-address {
- type inet:ipv6-prefix;
- }
- }
- }
- }
-
- grouping action-list {
- list action {
- key "order";
- leaf order {
- type int32;
- }
- uses action;
- }
- }
-
- grouping action {
- choice action {
- case output-action {
- leaf output-node-connector {
- type inet:uri;
- }
-
- leaf max-length {
- type uint16 {
- range "0..65294";
- }
- }
- }
-
- case controller-action {
- leaf max-length {
- type uint16 {
- range "0..65294";
- }
- }
- }
-
- case set-field {
- container match {
- uses match:match;
- }
- }
-
- case set-queue-action {
- leaf queue {
- type string;
- }
-
- leaf queue-id {
- type uint32;
- }
- }
-
- case pop-mpls-action {
- leaf ethernet-type {
- type uint16; // TODO: define ethertype type
- }
- }
-
- case set-mpls-ttl-action {
- leaf mpls-ttl {
- type uint8;
- }
- }
-
- case set-nw-ttl-action {
- leaf nw-ttl {
- type uint8;
- }
- }
-
- case push-pbb-action {
- leaf ethernet-type {
- type uint16; // TODO: define ethertype type
- }
- }
-
- case pop-pbb-action {
-
- }
-
- case push-mpls-action {
- leaf ethernet-type {
- type uint16; // TODO: define ethertype type
- }
- }
-
- case dec-mpls-ttl {
- }
-
- case dec-nw-ttl {
- }
-
- case drop-action {
- }
-
- case flood-action {
- }
-
- case flood-all-action {
- }
-
- case hw-path-action {
- }
-
- case loopback-action {
- }
-
- case pop-vlan-action {
- }
-
- case push-vlan-action {
- leaf ethernet-type {
- type uint16; // TODO: define ethertype type
- }
- leaf tag { // TPID - 16 bits
- type int32;
- }
- leaf pcp { // PCP - 3 bits
- type int32;
- }
- leaf cfi { // CFI - 1 bit (drop eligible)
- type vlan-cfi;
- }
- leaf vlan-id { // VID - 12 bits
- type l2t:vlan-id;
- }
-// leaf tci { //TCI = [PCP + CFI + VID]
-// }
-// leaf header { //header = [TPID + TCI]
-// }
- }
-
- case copy-ttl-out {
- }
-
- case copy-ttl-in {
- }
-
- case set-dl-dst-action {
- leaf address {
- type yang:mac-address;
- }
- }
-
- case set-dl-src-action {
- leaf address {
- type yang:mac-address;
- }
- }
- case group-action {
- leaf group {
- type string;
- }
-
- leaf group-id {
- type uint32;
- }
- }
-
- case set-dl-type-action {
- leaf dl-type {
- type l2t:ether-type;
- }
- }
-
- case set-next-hop-action {
- uses address;
- }
-
- case set-nw-dst-action {
- uses address;
- }
-
- case set-nw-src-action{
- uses address;
- }
-
- case set-nw-tos-action {
- leaf tos {
- type int32;
- }
- }
-
- case set-tp-dst-action {
- leaf port {
- type inet:port-number;
- }
- }
- case set-tp-src-action {
- leaf port {
- type inet:port-number;
- }
- }
- case set-vlan-cfi-action {
- leaf vlan-cfi {
- type vlan-cfi;
- }
- }
-
- case set-vlan-id-action {
- leaf vlan-id {
- type l2t:vlan-id;
- }
- }
-
- case set-vlan-pcp-action {
- leaf vlan-pcp {
- type l2t:vlan-pcp;
- }
- }
-
- case sw-path-action {
- }
- }
- }
-}
\ No newline at end of file
uses group-features;
}
+ grouping groups {
+ list group {
+ key "group-id";
+
+ uses group;
+ }
+ }
+
}
\ No newline at end of file
description "IP ECN (2 bits in ToS field).";
type uint8;
}
+
+ leaf ip-proto {
+ description "IP Proto (IPv4 or IPv6 Protocol Number).";
+ type inet:ip-version;
+ }
}
grouping "ipv4-match-fields" {
--- /dev/null
+module opendaylight-action-types {
+ namespace "urn:opendaylight:action:types";
+ prefix action;
+
+ import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
+ import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
+ import opendaylight-l2-types {prefix l2t; revision-date "2013-08-27";}
+ import opendaylight-match-types {prefix match; revision-date "2013-10-26";}
+
+ revision "2013-11-12" {
+ description "Initial revision of action service";
+ }
+
+ typedef vlan-cfi {
+ type int32;
+ }
+
+ grouping address {
+ choice address {
+ case ipv4 {
+ leaf ipv4-address {
+ type inet:ipv4-prefix;
+ }
+ }
+ case ipv6 {
+ leaf ipv6-address {
+ type inet:ipv6-prefix;
+ }
+ }
+ }
+ }
+
+ grouping action-list {
+ list action {
+ key "order";
+ leaf order {
+ type int32;
+ }
+ uses action;
+ }
+ }
+
+ grouping action {
+ choice action {
+ case output-action-case {
+ container output-action {
+ leaf output-node-connector {
+ type inet:uri;
+ }
+
+ leaf max-length {
+ type uint16 {
+ range "0..65294";
+ }
+ }
+ }
+ }
+
+ case controller-action-case {
+ container controller-action {
+ leaf max-length {
+ type uint16 {
+ range "0..65294";
+ }
+ }
+ }
+ }
+
+
+
+ case set-field-case {
+ container set-field {
+ uses match:match;
+ }
+ }
+
+
+ case set-queue-action-case {
+ container set-queue-action {
+ leaf queue {
+ type string;
+ }
+ leaf queue-id {
+ type uint32;
+ }
+ }
+ }
+
+ case pop-mpls-action-case {
+ container pop-mpls-action {
+ leaf ethernet-type {
+ type uint16; // TODO: define ethertype type
+ }
+ }
+ }
+
+
+ case set-mpls-ttl-action-case {
+ container set-mpls-ttl-action {
+ leaf mpls-ttl {
+ type uint8;
+ }
+ }
+ }
+
+
+ case set-nw-ttl-action-case {
+ container set-nw-ttl-action {
+ leaf nw-ttl {
+ type uint8;
+ }
+ }
+ }
+
+
+ case push-pbb-action-case {
+ container push-pbb-action {
+ leaf ethernet-type {
+ type uint16; // TODO: define ethertype type
+ }
+ }
+ }
+
+
+ case pop-pbb-action-case {
+ container pop-pbb-action {
+
+ }
+ }
+
+
+ case push-mpls-action-case {
+ container push-mpls-action {
+ leaf ethernet-type {
+ type uint16; // TODO: define ethertype type
+ }
+ }
+ }
+
+
+ case dec-mpls-ttl-case {
+ container dec-mpls-ttl {
+ }
+ }
+
+
+ case dec-nw-ttl-case {
+ container dec-nw-ttl {
+ }
+ }
+
+
+ case drop-action-case {
+ container drop-action {
+ }
+ }
+
+
+ case flood-action-case {
+ container flood-action {
+ }
+ }
+
+
+ case flood-all-action-case {
+ container flood-all-action {
+ }
+ }
+
+
+ case hw-path-action-case {
+ container hw-path-action {
+ }
+ }
+
+
+ case loopback-action-case {
+ container loopback-action {
+ }
+ }
+
+
+ case pop-vlan-action-case {
+ container pop-vlan-action {
+ }
+ }
+
+
+
+ case push-vlan-action-case {
+ container push-vlan-action {
+ leaf ethernet-type {
+ type uint16; // TODO: define ethertype type
+ }
+ leaf tag { // TPID - 16 bits
+ type int32;
+ }
+ leaf pcp { // PCP - 3 bits
+ type int32;
+ }
+ leaf cfi { // CFI - 1 bit (drop eligible)
+ type vlan-cfi;
+ }
+ leaf vlan-id { // VID - 12 bits
+ type l2t:vlan-id;
+ }
+// leaf tci { //TCI = [PCP + CFI + VID]
+// }
+// leaf header { //header = [TPID + TCI]
+// }
+ }
+ }
+
+ case copy-ttl-out-case {
+ container copy-ttl-out {
+ }
+ }
+
+
+ case copy-ttl-in-case {
+ container copy-ttl-in {
+ }
+ }
+
+
+ case set-dl-dst-action-case {
+ container set-dl-dst-action {
+ leaf address {
+ type yang:mac-address;
+ }
+ }
+ }
+
+
+ case set-dl-src-action-case {
+ container set-dl-src-action {
+ leaf address {
+ type yang:mac-address;
+ }
+ }
+
+ }
+ case group-action-case {
+ container group-action {
+ leaf group {
+ type string;
+ }
+
+ leaf group-id {
+ type uint32;
+ }
+ }
+ }
+
+ case set-dl-type-action-case {
+ container set-dl-type-action {
+ leaf dl-type {
+ type l2t:ether-type;
+ }
+ }
+ }
+
+
+ case set-next-hop-action-case {
+ container set-next-hop-action {
+ uses address;
+ }
+ }
+
+
+ case set-nw-dst-action-case {
+ container set-nw-dst-action {
+ uses address;
+ }
+ }
+
+
+ case set-nw-src-action-case {
+ container set-nw-src-action {
+ uses address;
+ }
+ }
+
+
+ case set-nw-tos-action-case {
+ container set-nw-tos-action {
+ leaf tos {
+ type int32;
+ }
+ }
+ }
+
+
+ case set-tp-dst-action-case {
+ container set-tp-dst-action {
+ leaf port {
+ type inet:port-number;
+ }
+ }
+
+ }
+ case set-tp-src-action-case {
+ container set-tp-src-action {
+ leaf port {
+ type inet:port-number;
+ }
+ }
+
+ }
+ case set-vlan-cfi-action-case {
+ container set-vlan-cfi-action {
+ leaf vlan-cfi {
+ type vlan-cfi;
+ }
+ }
+ }
+
+
+ case set-vlan-id-action-case {
+ container set-vlan-id-action {
+ leaf vlan-id {
+ type l2t:vlan-id;
+ }
+ }
+ }
+
+
+ case set-vlan-pcp-action-case {
+ container set-vlan-pcp-action {
+ leaf vlan-pcp {
+ type l2t:vlan-pcp;
+ }
+ }
+ }
+
+
+ case sw-path-action-case {
+ container sw-path-action {
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
import opendaylight-match-types {prefix match; revision-date "2013-10-26";}
import opendaylight-action-types {prefix action;}
+ import opendaylight-meter-types {prefix meter; revision-date "2013-09-18";}
revision "2013-10-26" {
description "Initial revision of flow service";
}
}
- grouping instruction {
- choice instruction {
- case go-to-table {
- leaf table_id {
- type uint8;
- }
+ grouping instruction {
+ choice instruction {
+ case go-to-table-case {
+ container go-to-table {
+ leaf table_id {
+ type uint8;
+ }
+ }
}
-
- case write-metadata {
- leaf metadata {
- type uint64;
- }
-
- leaf metadata-mask {
- type uint64;
- }
+
+ case write-metadata-case {
+ container write-metadata {
+ leaf metadata {
+ type uint64;
+ }
+
+ leaf metadata-mask {
+ type uint64;
+ }
+ }
}
-
- case write-actions {
- uses action:action-list;
+
+ case write-actions-case {
+ container write-actions {
+ uses action:action-list;
+ }
}
-
- case apply-actions {
- uses action:action-list;
+
+ case apply-actions-case {
+ container apply-actions {
+ uses action:action-list;
+ }
}
-
- case clear-actions {
- uses action:action-list;
+
+ case clear-actions-case {
+ container clear-actions {
+ uses action:action-list;
+ }
}
-
- case meter {
- leaf meter {
- type string;
- }
-
- leaf meter-id {
- type uint32;
- }
- }
- }
+
+ case meter-case {
+ container meter {
+ leaf meter-id {
+ type meter:meter-id;
+ }
+ }
+ }
+ }
}
typedef flow-mod-flags {
grouping flow-statistics {
leaf packet-count {
type yang:counter64;
- }
+ }
leaf byte-count {
type yang:counter64;
import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
import opendaylight-port-types {prefix port;revision-date "2013-09-25";}
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+ import opendaylight-table-types {prefix table;revision-date "2013-10-26";}
+ import opendaylight-flow-types {prefix flow;revision-date "2013-10-26";}
+ import opendaylight-group-types {prefix group;revision-date "2013-10-18";}
+ import opendaylight-meter-types {prefix meter;revision-date "2013-09-18";}
revision "2013-08-19" {
description "Flow Capable Node extensions to the Inventory model";
}
}
- grouping table {
-
+ typedef flow-id {
+ type uint32; // Note: This doesn't really belong here, and not sure if unint32 is right
+ }
+ grouping tables {
+ list table {
+ key "id";
+
+ leaf id {
+ type uint8;
+ }
+
+ uses table:table-features;
+
+ list flow {
+ key "id";
+
+ leaf id {
+ type flow-id;
+ }
+
+ uses flow:flow;
+ }
+ }
+ }
+
+ grouping meters {
+ list meter {
+ key "meter-id";
+ uses meter:meter;
+ }
}
grouping flow-node {
type string;
}
- container tables {
- uses feature;
- list table {
- uses table;
- }
- }
-
- container group-tables {
- uses feature;
- }
+ uses tables;
+ uses group:groups;
+ uses meters;
+ // TODO: ports
container supported-match-types {
list match-type {
--- /dev/null
+module opendaylight-inventory-config {
+ namespace "urn:opendaylight:inventory:config";
+ prefix inv-config;
+
+ import yang-ext {prefix ext; revision-date "2013-07-09";}
+ import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
+ import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
+ import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
+
+
+ revision "2013-08-19" {
+ description "Initial revision of Inventory model";
+ }
+ /** Base structure **/
+ container nodes {
+ list node {
+ key "id";
+ ext:context-instance "node-context";
+
+ uses inv:node;
+ }
+ }
+}
\ No newline at end of file
</scm>
<modules>
- <!-- Common APIs & Implementation -->
+ <!-- Common APIs & Implementation -->
<module>sal-common</module>
<module>sal-common-api</module>
<module>sal-common-impl</module>
<module>sal-connector-api</module>
<module>sal-rest-connector</module>
<module>sal-netconf-connector</module>
-
+
+ <module>zeromq-routingtable/implementation</module>
+ <module>sal-remoterpc-connector/implementation</module>
<!-- Clustered Data Store -->
<module>clustered-data-store/implementation</module>
<module>inventory-manager</module>
<module>statistics-manager</module>
<module>forwardingrules-manager</module>
-
+
<!-- Compability Packages -->
<module>compatibility</module>
- <module>zeromq-routingtable/implementation</module>
- <module>sal-zeromq-connector</module>
</modules>
<profiles>
<profile>
- <id>integrationtests</id>
- <activation>
- <activeByDefault>false</activeByDefault>
- </activation>
+ <id>integrationtests</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
<modules>
<module>sal-binding-it</module>
- <module>zeromq-routingtable/integrationtest</module>
<module>clustered-data-store/integrationtest</module>
- <module>test</module>
+ <!--module>zeromq-routingtable/integrationtest</module -->
+ <!--module>sal-remoterpc-connector/integrationtest</module -->
+ <!--module>test/sal-rest-connector-it</modulei -->
</modules>
</profile>
<profile>
- <id>IDE</id>
- <activation>
- <property>
- <name>m2e.version</name>
- </property>
- </activation>
- <build>
- <!-- Put the IDE's build output in a folder other than target, so that IDE builds don't interact with Maven builds -->
- <directory>target-ide</directory>
- </build>
+ <id>IDE</id>
+ <activation>
+ <property>
+ <name>m2e.version</name>
+ </property>
+ </activation>
+ <build>
+ <!-- Put the IDE's build output in a folder other than target,
+ so that IDE builds don't interact with Maven builds -->
+ <directory>target-ide</directory>
+ </build>
</profile>
</profiles>
<guava.version>14.0.1</guava.version>
<osgi.core.version>5.0.0</osgi.core.version>
<junit.version>4.8.1</junit.version>
+ <powermock.version>1.5.1</powermock.version>
+ <mockito.version>1.9.5</mockito.version>
<xtend.version>2.4.3</xtend.version>
<maven.clean.plugin.version>2.5</maven.clean.plugin.version>
<jacoco.version>0.5.3.201107060350</jacoco.version>
+ <sal.version>0.5.1-SNAPSHOT</sal.version> <!-- AD Sal version -->
+
<!-- Sonar properties using jacoco to retrieve integration test results -->
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<pluginRepositories>
<!-- OpenDayLight Repo Mirror -->
<pluginRepository>
- <id>opendaylight-mirror</id>
- <name>opendaylight-mirror</name>
- <url>${nexusproxy}/groups/public/</url>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- <releases>
- <enabled>true</enabled>
- <updatePolicy>never</updatePolicy>
- </releases>
+ <id>opendaylight-mirror</id>
+ <name>opendaylight-mirror</name>
+ <url>${nexusproxy}/groups/public/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ </releases>
</pluginRepository>
<!-- OpenDayLight Snapshot artifact -->
<pluginRepository>
- <id>opendaylight-snapshot</id>
- <name>opendaylight-snapshot</name>
- <url> ${nexusproxy}/repositories/opendaylight.snapshot/</url>
- <snapshots>
- <enabled>true</enabled>
- </snapshots>
- <releases>
- <enabled>false</enabled>
- </releases>
+ <id>opendaylight-snapshot</id>
+ <name>opendaylight-snapshot</name>
+ <url> ${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
</pluginRepository>
</pluginRepositories>
<repositories>
<!-- OpenDayLight Repo Mirror -->
<repository>
- <id>opendaylight-mirror</id>
- <name>opendaylight-mirror</name>
- <url>${nexusproxy}/groups/public/</url>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- <releases>
- <enabled>true</enabled>
- <updatePolicy>never</updatePolicy>
- </releases>
+ <id>opendaylight-mirror</id>
+ <name>opendaylight-mirror</name>
+ <url>${nexusproxy}/groups/public/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ </releases>
</repository>
<!-- OpenDayLight Snapshot artifact -->
<repository>
- <id>opendaylight-snapshot</id>
- <name>opendaylight-snapshot</name>
- <url> ${nexusproxy}/repositories/opendaylight.snapshot/</url>
- <snapshots>
- <enabled>true</enabled>
- </snapshots>
- <releases>
- <enabled>false</enabled>
- </releases>
+ <id>opendaylight-snapshot</id>
+ <name>opendaylight-snapshot</name>
+ <url> ${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
</repository>
</repositories>
<artifactId>yang-data-api</artifactId>
<version>${yang.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ <version>${yang.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-model-api</artifactId>
<artifactId>sal-connector-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>${sal.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
<!-- Supporting Libraries -->
<dependency>
<artifactId>org.eclipse.xtend.lib</artifactId>
<version>${xtend.version}</version>
</dependency>
-
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.core.version}</version>
+ </dependency>
<!-- Testing Dependencies -->
<dependency>
<groupId>junit</groupId>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
- <version>1.9.5</version>
+ <version>${mockito.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<artifactId>maven-bundle-plugin</artifactId>
<version>${bundle.plugin.version}</version>
<extensions>true</extensions>
- <!--executions>
- <execution>
- <id>bundle-manifest</id>
- <phase>process-classes</phase>
- <goals>
- <goal>manifest</goal>
- </goals>
- </execution>
- </executions-->
+ <!--executions> <execution> <id>bundle-manifest</id>
+ <phase>process-classes</phase> <goals> <goal>manifest</goal> </goals> </execution>
+ </executions -->
<configuration>
<instructions>
<Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
</plugin>
- <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+ <!--This plugin's configuration is used to store Eclipse
+ m2e settings only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
</goals>
</pluginExecutionFilter>
<action>
- <ignore/>
+ <ignore />
</action>
</pluginExecution>
<pluginExecution>
</goals>
</pluginExecutionFilter>
<action>
- <ignore/>
+ <ignore />
</action>
</pluginExecution>
<pluginExecution>
</goals>
</pluginExecutionFilter>
<action>
- <ignore/>
+ <ignore />
</action>
</pluginExecution>
</pluginExecutions>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ <version>2010.09.24.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-base</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-statistics</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+package org.opendaylight.controller.sal.binding.test;
+
+import junit.framework.Assert;
+
+
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+public class AugmentationVerifier<T extends Augmentable<T>> {
+
+ private T object;
+
+ public AugmentationVerifier(T objectToVerify) {
+ this.object = objectToVerify;
+ }
+
+ public AugmentationVerifier<T> assertHasAugmentation(Class<? extends Augmentation<T>> augmentation) {
+ assertHasAugmentation(object, augmentation);
+ return (AugmentationVerifier<T>) this;
+ }
+
+ public static <T extends Augmentable<T>> void assertHasAugmentation(T object,
+ Class<? extends Augmentation<T>> augmentation) {
+ Assert.assertNotNull(object);
+ Assert.assertNotNull("Augmentation " + augmentation.getSimpleName() + " is not present.", object.getAugmentation(augmentation));
+ }
+
+ public static <T extends Augmentable<T>> AugmentationVerifier<T> from(T obj) {
+ return new AugmentationVerifier<T>(obj);
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test;
+
+public class BindingTestUtilities {
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.binding.test.AugmentationVerifier;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.Duration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.DurationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsKey;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.collect.FluentIterable;
+
+import static org.junit.Assert.*;
+
+public class MultipleAugmentationPuts extends AbstractDataServiceTest implements DataChangeListener {
+
+ private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+ private static final String NODE_ID = "openflow:1";
+
+ private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+
+ private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
+ NODE_ID);
+
+ private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
+ .toInstance();
+
+ private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier
+ .builder(NODES_INSTANCE_ID_BA) //
+ .child(Node.class, NODE_KEY).toInstance();
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Nodes.QNAME) //
+ .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+ .toInstance();
+ private DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedChangeEvent;
+
+ /**
+ * Test for Bug 148
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testAugmentSerialization() throws Exception {
+
+ baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
+
+ Node flowCapableNode = createTestNode(FlowCapableNode.class, flowCapableNodeAugmentation());
+ commitNodeAndVerifyTransaction(flowCapableNode);
+
+ assertNotNull(receivedChangeEvent);
+ verifyNode((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(), flowCapableNode);
+
+ Nodes nodes = checkForNodes();
+ verifyNode(nodes, flowCapableNode).assertHasAugmentation(FlowCapableNode.class);
+ ;
+ assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+ Node meterStatsNode = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics());
+ commitNodeAndVerifyTransaction(meterStatsNode);
+
+ assertNotNull(receivedChangeEvent);
+ verifyNode((Nodes) receivedChangeEvent.getUpdatedOperationalSubtree(), meterStatsNode);
+
+ assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+
+ Node mergedNode = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
+
+ AugmentationVerifier.from(mergedNode) //
+ .assertHasAugmentation(FlowCapableNode.class) //
+ .assertHasAugmentation(NodeMeterStatistics.class);
+
+ assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+
+ Node meterStatsNodeWithDuration = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics(5, true));
+ commitNodeAndVerifyTransaction(meterStatsNodeWithDuration);
+
+
+ Node nodeWithUpdatedList = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
+ AugmentationVerifier.from(nodeWithUpdatedList) //
+ .assertHasAugmentation(FlowCapableNode.class) //
+ .assertHasAugmentation(NodeMeterStatistics.class);
+
+ List<MeterStats> meterStats = nodeWithUpdatedList.getAugmentation(NodeMeterStatistics.class).getMeterStatistics().getMeterStats();
+ assertNotNull(meterStats);
+ assertFalse(meterStats.isEmpty());
+ assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
+ testNodeRemove();
+ }
+
+ private <T extends Augmentation<Node>> Node createTestNode(Class<T> augmentationClass, T augmentation) {
+ NodeBuilder nodeBuilder = new NodeBuilder();
+ nodeBuilder.setId(new NodeId(NODE_ID));
+ nodeBuilder.setKey(NODE_KEY);
+ nodeBuilder.addAugmentation(augmentationClass, augmentation);
+ return nodeBuilder.build();
+ }
+
+ private DataModificationTransaction commitNodeAndVerifyTransaction(Node original) throws Exception {
+ DataModificationTransaction transaction = baDataService.beginTransaction();
+ transaction.putOperationalData(NODE_INSTANCE_ID_BA, original);
+ RpcResult<TransactionStatus> result = transaction.commit().get();
+ assertEquals(TransactionStatus.COMMITED, result.getResult());
+ return transaction;
+ }
+
+ private void testNodeRemove() throws Exception {
+ DataModificationTransaction transaction = baDataService.beginTransaction();
+ transaction.removeOperationalData(NODE_INSTANCE_ID_BA);
+ RpcResult<TransactionStatus> result = transaction.commit().get();
+ assertEquals(TransactionStatus.COMMITED, result.getResult());
+
+ Node node = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
+ assertNull(node);
+ }
+
+ private AugmentationVerifier<Node> verifyNode(Nodes nodes, Node original) {
+ assertNotNull(nodes);
+ assertNotNull(nodes.getNode());
+ assertEquals(1, nodes.getNode().size());
+ Node readedNode = nodes.getNode().get(0);
+ assertEquals(original.getId(), readedNode.getId());
+ assertEquals(original.getKey(), readedNode.getKey());
+ return new AugmentationVerifier<Node>(readedNode);
+ }
+
+ private void assertBindingIndependentVersion(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier nodeId) {
+ CompositeNode node = biDataService.readOperationalData(nodeId);
+ assertNotNull(node);
+ }
+
+ private Nodes checkForNodes() {
+ return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
+ }
+
+ private NodeMeterStatistics nodeMeterStatistics() {
+ return nodeMeterStatistics(10, false);
+ }
+
+ private NodeMeterStatistics nodeMeterStatistics(int count, boolean setDuration) {
+ NodeMeterStatisticsBuilder nmsb = new NodeMeterStatisticsBuilder();
+ MeterStatisticsBuilder meterStats = new MeterStatisticsBuilder();
+
+ List<MeterStats> stats = new ArrayList<>(count);
+ for (int i = 0; i <= count; i++) {
+ MeterStatsBuilder statistic = new MeterStatsBuilder();
+ statistic.setKey(new MeterStatsKey(new MeterId((long) i)));
+ statistic.setByteInCount(new Counter64(BigInteger.valueOf(34590 + i)));
+ statistic.setFlowCount(new Counter32(4569L + i));
+
+ if (setDuration) {
+ DurationBuilder duration = new DurationBuilder();
+ duration.setNanosecond(new Counter32(70L));
+ statistic.setDuration(duration.build());
+ }
+
+ stats.add(statistic.build());
+ }
+ meterStats.setMeterStats(stats);
+ nmsb.setMeterStatistics(meterStats.build());
+ return nmsb.build();
+ }
+
+ private FlowCapableNode flowCapableNodeAugmentation() {
+ FlowCapableNodeBuilder fnub = new FlowCapableNodeBuilder();
+ fnub.setHardware("Hardware Foo");
+ fnub.setManufacturer("Manufacturer Foo");
+ fnub.setSerialNumber("Serial Foo");
+ fnub.setDescription("Description Foo");
+ fnub.setSoftware("JUnit emulated");
+ FlowCapableNode fnu = fnub.build();
+ return fnu;
+ }
+
+ @Override
+ public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ receivedChangeEvent = change;
+ }
+
+}
+
+
+
+
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
List<Action> actionList = new ArrayList<>();
PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
popMplsAction.setEthernetType(34);
- actionList.add(new ActionBuilder().setAction(popMplsAction.build()).setOrder(10).build());
+ actionList.add(new ActionBuilder().setAction(new PopMplsActionCaseBuilder().setPopMplsAction(popMplsAction.build()).build()).setOrder(10).build());
applyActions.setAction(actionList );
-
-
- instruction.setInstruction(applyActions.build());
+ instruction.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions.build()).build());
List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
match.setLayer4Match(new TcpMatchBuilder().build());
flow.setMatch(match.build());
- System.out.println("Putting the configuration Data................");
path1 = InstanceIdentifier.builder(Flows.class).child(Flow.class, key).toInstance();
// DataObject cls = (DataObject) modification.readConfigurationData(path1);
modification.putConfigurationData(path1, flow.build());
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-
-
-
-
-
-
-
-
-
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
-
-
-
-
-
-
-
-
-
-
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
import org.opendaylight.controller.sal.binding.impl.connect.dom.CommitHandlersTransactions;
import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
- private static final long FLOW_ID = 1234;
- private static final String NODE_ID = "node:1";
-
- private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modificationCapture;
+ private static final QName TABLE_ID_QNAME = QName.create(Table.QNAME, "id");
+ private static final String NODE_ID = "node:1";
+ private static final FlowId FLOW_ID = new FlowId(1234L);
+ private static final Short TABLE_ID = Short.valueOf((short) 0);
private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+ private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID);
+
+ private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modificationCapture;
private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
NODE_ID);
.toInstance();
private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
- private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID, NODE_REF);
-
private static final Map<QName, Object> FLOW_KEY_BI = //
- ImmutableMap.<QName, Object> of(FLOW_ID_QNAME, FLOW_ID, FLOW_NODE_QNAME, NODE_INSTANCE_ID_BI);
+ ImmutableMap.<QName, Object> of(FLOW_ID_QNAME, FLOW_ID.getValue());
+
+ private static final Map<QName, Object> TABLE_KEY_BI = //
+ ImmutableMap.<QName, Object> of(TABLE_ID_QNAME, TABLE_ID);;
private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier FLOW_INSTANCE_ID_BI = //
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
- .node(Flows.QNAME) //
+ .node(Nodes.QNAME) //
+ .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+ .nodeWithKey(Table.QNAME, TABLE_KEY_BI) //
.nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
.toInstance();
-
- private static final InstanceIdentifier<Flows> FLOWS_PATH_BA = //
- InstanceIdentifier.builder(Flows.class) //
- .toInstance();
-
-
+ private static final TableKey TABLE_KEY_BA = new TableKey((short) 0);
+
+ private static final InstanceIdentifier<Flow> FLOWS_PATH_BA = //
+ InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) //
+ .augmentation(FlowCapableNode.class) //
+ .child(Table.class, TABLE_KEY_BA) //
+ .child(Flow.class) //
+ .toInstance();
+
private static final InstanceIdentifier<Flow> FLOW_INSTANCE_ID_BA = //
- InstanceIdentifier.builder(Flows.class) //
+ InstanceIdentifier.builder(FLOWS_PATH_BA.firstIdentifierOf(Table.class)) //
.child(Flow.class, FLOW_KEY) //
.toInstance();
-
+
@Test
public void simpleModifyOperation() throws Exception {
+
assertNull(biDataService.readConfigurationData(FLOW_INSTANCE_ID_BI));
-
+
registerCommitHandler();
-
- CompositeNode domflow = createXmlFlow();
+
+ CompositeNode domflow = createTestFlow();
DataModificationTransaction biTransaction = biDataService.beginTransaction();
biTransaction.putConfigurationData(FLOW_INSTANCE_ID_BI, domflow);
RpcResult<TransactionStatus> biResult = biTransaction.commit().get();
assertNotNull(flow);
assertNotNull(flow.getMatch());
assertEquals(TransactionStatus.COMMITED, biResult.getResult());
-
- }
-
+ }
private void registerCommitHandler() {
DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> flowTestCommitHandler = new DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>() {
-
-
+
@Override
public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
modificationCapture = modification;
return CommitHandlersTransactions.allwaysSuccessfulTransaction(modification);
}
-
-
+
};
- Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> registration = baDataService.registerCommitHandler(FLOWS_PATH_BA, flowTestCommitHandler);
+ Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> registration = baDataService
+ .registerCommitHandler(FLOWS_PATH_BA, flowTestCommitHandler);
assertNotNull(registration);
}
-
- private CompositeNode createXmlFlow() {
-
- FlowBuilder flow = new FlowBuilder();
- MatchBuilder match = new MatchBuilder();
- VlanMatchBuilder vlanBuilder = new VlanMatchBuilder();
- VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
- VlanId vlanId = new VlanId(10);
- vlanBuilder.setVlanId(vlanIdBuilder.setVlanId(vlanId).build());
- match.setVlanMatch(vlanBuilder.build());
+ private CompositeNode createTestFlow() {
+ FlowBuilder flow = new FlowBuilder();
flow.setKey(FLOW_KEY);
+ Short tableId = 0;
+ flow.setTableId(tableId);
+ MatchBuilder match = new MatchBuilder();
+ match.setIpMatch(new IpMatchBuilder().setIpProto(IpVersion.Ipv4).build());
+ Ipv4MatchBuilder ipv4Match = new Ipv4MatchBuilder();
+ // ipv4Match.setIpv4Destination(new Ipv4Prefix(cliInput.get(4)));
+ Ipv4Prefix prefix = new Ipv4Prefix("10.0.0.1/24");
+ ipv4Match.setIpv4Destination(prefix);
+ Ipv4Match i4m = ipv4Match.build();
+ match.setLayer3Match(i4m);
flow.setMatch(match.build());
- flow.setNode(NODE_REF);
- InstructionsBuilder instructions = new InstructionsBuilder();
- InstructionBuilder instruction = new InstructionBuilder();
- instruction.setOrder(10);
- ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
- List<Action> actionList = new ArrayList<>();
- PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
- popMplsAction.setEthernetType(34);
- actionList.add(new ActionBuilder().setAction(popMplsAction.build()).setOrder(0).build());
- applyActions.setAction(actionList );
-
- instruction.setInstruction(applyActions.build());
+ // Create a drop action
+ /*
+ * Note: We are mishandling drop actions DropAction dropAction = new
+ * DropActionBuilder().build(); ActionBuilder ab = new ActionBuilder();
+ * ab.setAction(dropAction);
+ */
+
+ DecNwTtl decNwTtl = new DecNwTtlBuilder().build();
+ ActionBuilder ab = new ActionBuilder();
+ ActionKey actionKey = new ActionKey(0);
+ ab.setKey(actionKey );
+ ab.setAction(new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build());
+
+ // Add our drop action to a list
+ List<Action> actionList = new ArrayList<Action>();
+ actionList.add(ab.build());
+
+ // Create an Apply Action
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ // Wrap our Apply Action in an Instruction
+ InstructionBuilder ib = new InstructionBuilder();
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ // Put our Instruction in a list of Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ instructions.add(ib.build());
+ isb.setInstruction(instructions);
- List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
- instructions.setInstruction(instructionList );
+ // Add our instructions to the flow
+ flow.setInstructions(isb.build());
- flow.setInstructions(instructions.build());
-
+ flow.setPriority(2);
+ flow.setFlowName("Foo Name");
CompositeNode domFlow = mappingService.toDataDom(flow.build());
return domFlow;
}
mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
systemProperty("osgi.bundles.defaultStartLevel").value("4"),
-
-
mdSalCoreBundles(),
bindingAwareSalBundles(),
configMinumumBundles(),
// BASE Models
- baseModelBundles(), flowCapableModelBundles(), junitAndMockitoBundles());
+ baseModelBundles(),
+ flowCapableModelBundles(),
+ junitAndMockitoBundles());
}
}
*/
package org.opendaylight.controller.sal.common.util;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
return ret;
}
- private static class RpcResultTO<T> implements RpcResult<T> {
+ private static class RpcResultTO<T> implements RpcResult<T>, Serializable {
private final Collection<RpcError> errors;
private final T result;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
-public abstract class AbstractConsumer implements Consumer, BundleActivator {
+public abstract class AbstractConsumer implements Consumer, BundleActivator,ServiceTrackerCustomizer<Broker, Broker> {
+
+
+
+
+ private BundleContext context;
+ private ServiceTracker<Broker, Broker> tracker;
+ private Broker broker;
- Broker broker;
- ServiceReference<Broker> brokerRef;
@Override
public final void start(BundleContext context) throws Exception {
+ this.context = context;
this.startImpl(context);
- brokerRef = context.getServiceReference(Broker.class);
- broker = context.getService(brokerRef);
- broker.registerConsumer(this,context);
+ tracker = new ServiceTracker<>(context, Broker.class, this);
+ tracker.open();
}
public final void stop(BundleContext context) throws Exception {
stopImpl(context);
broker = null;
- if(brokerRef != null) {
- context.ungetService(brokerRef);
- }
+ tracker.close();
}
protected void startImpl(BundleContext context) {
return Collections.emptySet();
}
+
+ @Override
+ public Broker addingService(ServiceReference<Broker> reference) {
+ if(broker == null) {
+ broker = context.getService(reference);
+ broker.registerConsumer(this, context);
+ return broker;
+ }
+
+ return null;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<Broker> reference, Broker service) {
+ // NOOP
+ }
+
+ @Override
+ public void removedService(ServiceReference<Broker> reference, Broker service) {
+ stopImpl(context);
+ }
}
import java.util.Collection;
import java.util.Collections;
+import javax.naming.Context;
+
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
-public abstract class AbstractProvider implements BundleActivator, Provider {
+public abstract class AbstractProvider implements BundleActivator, Provider,ServiceTrackerCustomizer<Broker, Broker> {
- private ServiceReference<Broker> brokerRef;
private Broker broker;
-
+ private BundleContext context;
+ private ServiceTracker<Broker, Broker> tracker;
@Override
public Collection<ProviderFunctionality> getProviderFunctionality() {
return Collections.emptySet();
@Override
public final void start(BundleContext context) throws Exception {
- brokerRef = context.getServiceReference(Broker.class);
- broker = context.getService(brokerRef);
-
+ this.context = context;
this.startImpl(context);
-
- broker.registerProvider(this,context);
+ tracker = new ServiceTracker<>(context, Broker.class, this);
+ tracker.open();
}
protected void startImpl(BundleContext context) {
@Override
public final void stop(BundleContext context) throws Exception {
+ broker = null;
+ tracker.close();
+ tracker = null;
stopImpl(context);
}
+ @Override
+ public Broker addingService(ServiceReference<Broker> reference) {
+ if(broker == null) {
+ broker = context.getService(reference);
+ broker.registerProvider(this, context);
+ return broker;
+ }
+
+ return null;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<Broker> reference, Broker service) {
+ // NOOP
+ }
+
+ @Override
+ public void removedService(ServiceReference<Broker> reference, Broker service) {
+ stopImpl(context);
+ }
+
}
import org.opendaylight.controller.sal.core.api.data.DataStore
import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter
import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.controller.sal.dom.broker.impl.RpcRouterImpl
class BrokerConfigActivator implements AutoCloseable {
val emptyProperties = new Hashtable<String, String>();
broker.setBundleContext(context);
-
+ broker.setRouter(new RpcRouterImpl("Rpc router"))
schemaService = new SchemaServiceImpl();
schemaService.setContext(context);
schemaService.setParser(new YangParserImpl());
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+ <relativePath>../..</relativePath>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>sal-remoterpc-connector</artifactId>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <zeromq.version>0.3.1</zeromq.version>
+ <jackson.version>1.9.8</jackson.version>
+ <stax.version>1.0.1</stax.version>
+ </properties>
+
+ <dependencies>
+ <!-- MD Sal interdependencies -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sal-core-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sal-connector-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>zeromq-routingtable.implementation</artifactId>
+ <!-- TODO: fix the version. Why is it not MD Sal project version?-->
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+
+ <!-- AD Sal -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ </dependency>
+
+ <!-- Yang tools -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+
+ <!-- Third Party -->
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.zeromq</groupId>
+ <artifactId>jeromq</artifactId>
+ <version>${zeromq.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId> org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-core-asl</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>stax</groupId>
+ <artifactId>stax-api</artifactId>
+ <version>${stax.version}</version>
+ </dependency>
+
+ <!-- Tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ </dependency>
+
+ </dependencies>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${bundle.plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ *,
+ !org.codehaus.enunciate.jaxrs
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.controller.config.yang.md.sal.remote.rpc,
+ org.opendaylight.controller.sal.connector.remoterpc,
+ org.opendaylight.controller.sal.connector.remoterpc.*
+ </Export-Package>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ </instructions>
+ </configuration>
+ </plugin>
+
+
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ </codeGeneratorClass>
+ <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>
+ urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
+ </namespaceToPackage1>
+ </additionalConfiguration>
+ </generator>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>target/site/models</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-jmx-generator-plugin</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ <type>jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+/**
+* Generated file
+
+* Generated from: yang module name: odl-sal-dom-rpc-remote-cfg yang module local name: remote-zeromq-rpc-server
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Dec 05 14:25:21 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.md.sal.remote.rpc;
+
+import org.opendaylight.controller.sal.connector.remoterpc.Client;
+import org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcProvider;
+import org.opendaylight.controller.sal.connector.remoterpc.RoutingTableProvider;
+import org.opendaylight.controller.sal.connector.remoterpc.ServerImpl;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.osgi.framework.BundleContext;
+
+/**
+*
+*/
+public final class ZeroMQServerModule extends org.opendaylight.controller.config.yang.md.sal.remote.rpc.AbstractZeroMQServerModule
+ {
+
+ private static final Integer ZEROMQ_ROUTER_PORT = 5554;
+ private BundleContext bundleContext;
+
+ public ZeroMQServerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public ZeroMQServerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ ZeroMQServerModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ protected void customValidation(){
+ // Add custom validation for module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+
+ Broker broker = getDomBrokerDependency();
+ RoutingTableProvider provider = new RoutingTableProvider(bundleContext);
+
+
+ final int port = getPort() != null ? getPort() : ZEROMQ_ROUTER_PORT;
+
+ ServerImpl serverImpl = new ServerImpl(port);
+
+ Client clientImpl = new Client();
+ RemoteRpcProvider facade = new RemoteRpcProvider(serverImpl, clientImpl);
+
+ facade.setRoutingTableProvider(provider );
+
+ broker.registerProvider(facade, bundleContext);
+ return facade;
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+}
--- /dev/null
+/**
+* Generated file
+
+* Generated from: yang module name: odl-sal-dom-rpc-remote-cfg yang module local name: remote-zeromq-rpc-server
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Dec 05 14:25:21 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.md.sal.remote.rpc;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.spi.Module;
+import org.osgi.framework.BundleContext;
+
+/**
+*
+*/
+public class ZeroMQServerModuleFactory extends org.opendaylight.controller.config.yang.md.sal.remote.rpc.AbstractZeroMQServerModuleFactory
+{
+
+ @Override
+ public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+ ZeroMQServerModule module = (ZeroMQServerModule) super.createModule(instanceName, dependencyResolver, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+ @Override
+ public Module createModule(String instanceName, DependencyResolver dependencyResolver,
+ DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
+ ZeroMQServerModule module = (ZeroMQServerModule) super.createModule(instanceName, dependencyResolver, old,bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+}
--- /dev/null
+/*
+ * 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.sal.common.util.RpcErrors;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.*;
+
+import static com.google.common.base.Preconditions.*;
+
+/**
+ * An implementation of {@link RpcImplementation} that makes remote RPC calls
+ */
+public class Client implements RemoteRpcClient {
+
+ private final Logger _logger = LoggerFactory.getLogger(Client.class);
+
+ private final LinkedBlockingQueue<MessageWrapper> requestQueue = new LinkedBlockingQueue<MessageWrapper>(100);
+
+ private final ExecutorService pool = Executors.newSingleThreadExecutor();
+ private final long TIMEOUT = 5000; // in ms
+
+ private RoutingTableProvider routingTableProvider;
+
+ public RoutingTableProvider getRoutingTableProvider() {
+ return routingTableProvider;
+ }
+
+ public void setRoutingTableProvider(RoutingTableProvider routingTableProvider) {
+ this.routingTableProvider = routingTableProvider;
+ }
+
+ public LinkedBlockingQueue<MessageWrapper> getRequestQueue() {
+ return requestQueue;
+ }
+
+ @Override
+ public Set<QName> getSupportedRpcs() {
+ // TODO: Find the entries from routing table
+ return Collections.emptySet();
+ }
+
+ public void start() {
+ pool.execute(new Sender(this));
+
+ }
+
+ public void stop() {
+
+ _logger.debug("Client stopping...");
+ Context.getInstance().getZmqContext().term();
+ _logger.debug("ZMQ context terminated");
+
+ pool.shutdown(); // intiate shutdown
+ try {
+ if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
+ pool.shutdownNow();
+ if (!pool.awaitTermination(10, TimeUnit.SECONDS))
+ _logger.error("Client thread pool did not shut down");
+ }
+ } catch (InterruptedException e) {
+ // (Re-)Cancel if current thread also interrupted
+ pool.shutdownNow();
+ // Preserve interrupt status
+ Thread.currentThread().interrupt();
+ }
+ _logger.debug("Client stopped");
+ }
+
+ @Override
+ public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+
+ RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+ routeId.setType(rpc);
+
+ String address = lookupRemoteAddress(routeId);
+
+ Message request = new Message.MessageBuilder().type(Message.MessageType.REQUEST)
+ .sender(Context.getInstance().getLocalUri()).recipient(address).route(routeId)
+ .payload(XmlUtils.compositeNodeToXml(input)).build();
+
+ List<RpcError> errors = new ArrayList<RpcError>();
+
+ try (SocketPair pair = new SocketPair()) {
+
+ MessageWrapper messageWrapper = new MessageWrapper(request, pair.getSender());
+ process(messageWrapper);
+ Message response = parseMessage(pair.getReceiver());
+
+ CompositeNode payload = XmlUtils.xmlToCompositeNode((String) response.getPayload());
+
+ return Rpcs.getRpcResult(true, payload, errors);
+
+ } catch (Exception e) {
+ collectErrors(e, errors);
+ return Rpcs.getRpcResult(false, null, errors);
+ }
+
+ }
+
+ public void process(MessageWrapper msg) throws TimeoutException, InterruptedException {
+ _logger.debug("Processing message [{}]", msg);
+
+ boolean success = requestQueue.offer(msg, TIMEOUT, TimeUnit.MILLISECONDS);
+ if (!success)
+ throw new TimeoutException("Queue is full");
+ }
+
+ /**
+ * Block on socket for reply
+ *
+ * @param receiver
+ * @return
+ */
+ private Message parseMessage(ZMQ.Socket receiver) throws IOException, ClassNotFoundException {
+ return (Message) Message.deserialize(receiver.recv());
+ }
+
+ /**
+ * Find address for the given route identifier in routing table
+ *
+ * @param routeId
+ * route identifier
+ * @return remote network address
+ */
+ private String lookupRemoteAddress(RpcRouter.RouteIdentifier routeId) {
+ checkNotNull(routeId, "route must not be null");
+
+ Optional<RoutingTable<String, String>> routingTable = routingTableProvider.getRoutingTable();
+ checkNotNull(routingTable.isPresent(), "Routing table is null");
+
+ Set<String> addresses = routingTable.get().getRoutes(routeId.toString());
+ checkNotNull(addresses, "Address not found for route [%s]", routeId);
+ checkState(addresses.size() == 1, "Multiple remote addresses found for route [%s], \nonly 1 expected", routeId); // its
+ // a
+ // global
+ // service.
+
+ String address = addresses.iterator().next();
+ checkNotNull(address, "Address not found for route [%s]", routeId);
+
+ return address;
+ }
+
+ private void collectErrors(Exception e, List<RpcError> errors) {
+ if (e == null)
+ return;
+ if (errors == null)
+ errors = new ArrayList<RpcError>();
+
+ errors.add(RpcErrors.getRpcError(null, null, null, null, e.getMessage(), null, e.getCause()));
+ for (Throwable t : e.getSuppressed()) {
+ errors.add(RpcErrors.getRpcError(null, null, null, null, t.getMessage(), null, t));
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ stop();
+ }
+}
--- /dev/null
+/*
+ * 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.connector.remoterpc;
+
+import org.zeromq.ZMQ;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+
+/**
+ * Provides a ZeroMQ Context object
+ */
+public class Context {
+ private ZMQ.Context zmqContext = ZMQ.context(1);
+ private String uri;
+
+ private static Context _instance = new Context();
+
+ private Context() {}
+
+ public static Context getInstance(){
+ return _instance;
+ }
+
+ public ZMQ.Context getZmqContext(){
+ return this.zmqContext;
+ }
+
+ public String getLocalUri(){
+ uri = (uri != null) ? uri
+ : new StringBuilder("tcp://").append(getIpAddress()).append(":")
+ .append(getRpcPort()).toString();
+
+ return uri;
+ }
+
+ public String getRpcPort(){
+ String rpcPort = (System.getProperty("rpc.port") != null)
+ ? System.getProperty("rpc.port")
+ : "5554";
+
+ return rpcPort;
+ }
+
+ private String getIpAddress(){
+ String ipAddress = (System.getProperty("local.ip") != null)
+ ? System.getProperty("local.ip")
+ : findIpAddress();
+
+ return ipAddress;
+ }
+
+ /**
+ * Finds IPv4 address of the local VM
+ * TODO: This method is non-deterministic. There may be more than one IPv4 address. Cant say which
+ * address will be returned. Read IP from a property file or enhance the code to make it deterministic.
+ * Should we use IP or hostname?
+ *
+ * @return
+ */
+ private String findIpAddress() {
+ String hostAddress = null;
+ Enumeration e = null;
+ try {
+ e = NetworkInterface.getNetworkInterfaces();
+ } catch (SocketException e1) {
+ e1.printStackTrace();
+ }
+ while (e.hasMoreElements()) {
+
+ NetworkInterface n = (NetworkInterface) e.nextElement();
+
+ Enumeration ee = n.getInetAddresses();
+ while (ee.hasMoreElements()) {
+ InetAddress i = (InetAddress) ee.nextElement();
+ if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
+ hostAddress = i.getHostAddress();
+ }
+ }
+ return hostAddress;
+
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+
+public interface RemoteRpcClient extends RpcImplementation,AutoCloseable{
+
+
+ void setRoutingTableProvider(RoutingTableProvider provider);
+
+ void stop();
+
+ void start();
+}
--- /dev/null
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
+import org.opendaylight.controller.sal.connector.remoterpc.Client;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public class RemoteRpcProvider implements
+ RemoteRpcServer,
+ RemoteRpcClient,
+ Provider {
+
+ private final ServerImpl server;
+ private final Client client;
+ private RoutingTableProvider provider;
+
+ @Override
+ public void setRoutingTableProvider(RoutingTableProvider provider) {
+ this.provider = provider;
+ server.setRoutingTableProvider(provider);
+ client.setRoutingTableProvider(provider);
+ }
+
+ @Override
+ public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+ return client.invokeRpc(rpc, input);
+ }
+
+ @Override
+ public Set<QName> getSupportedRpcs() {
+ return client.getSupportedRpcs();
+ }
+
+
+ public RemoteRpcProvider(ServerImpl server, Client client) {
+ this.server = server;
+ this.client = client;
+ }
+
+ public void setBrokerSession(ProviderSession session) {
+ server.setBrokerSession(session);
+ }
+ public void setServerPool(ExecutorService serverPool) {
+ server.setServerPool(serverPool);
+ }
+ public void start() {
+ client.setRoutingTableProvider(provider);
+ server.setRoutingTableProvider(provider);
+ server.start();
+ client.start();
+ }
+ public void onRouteUpdated(String key, Set values) {
+ server.onRouteUpdated(key, values);
+ }
+ public void onRouteDeleted(String key) {
+ server.onRouteDeleted(key);
+ }
+
+
+ @Override
+ public Collection<ProviderFunctionality> getProviderFunctionality() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+ @Override
+ public void onSessionInitiated(ProviderSession session) {
+ server.setBrokerSession(session);
+ start();
+ }
+
+
+ public void close() throws Exception {
+ server.close();
+ client.close();
+ }
+
+
+
+
+ @Override
+ public void stop() {
+ server.stop();
+ client.stop();
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+
+public interface RemoteRpcServer extends AutoCloseable {
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+import com.google.common.base.Optional;
+
+public class RoutingTableProvider implements AutoCloseable {
+
+ @SuppressWarnings("rawtypes")
+ final ServiceTracker<RoutingTable,RoutingTable> tracker;
+
+
+ public RoutingTableProvider(BundleContext ctx) {
+ @SuppressWarnings("rawtypes")
+ ServiceTracker<RoutingTable, RoutingTable> rawTracker = new ServiceTracker<>(ctx, RoutingTable.class, null);
+ tracker = rawTracker;
+ tracker.open();
+ }
+
+ public Optional<RoutingTable<String, String>> getRoutingTable() {
+ @SuppressWarnings("unchecked")
+ RoutingTable<String,String> tracked = tracker.getService();
+ return Optional.fromNullable(tracked);
+ }
+
+ @Override
+ public void close() throws Exception {
+ tracker.close();
+ }
+}
--- /dev/null
+/*
+ * 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.connector.remoterpc;
+
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import java.io.IOException;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A class encapsulating {@link ZMQ.Socket} of type {@link ZMQ.REQ}.
+ * It adds following capabilities:
+ * <li> Retry logic - Tries 3 times before giving up
+ * <li> Request times out after {@link TIMEOUT} property
+ * <li> The limitation of {@link ZMQ.REQ}/{@link ZMQ.REP} pair is that no 2 requests can be sent before
+ * the response for the 1st request is received. To overcome that, this socket queues all messages until
+ * the previous request has been responded.
+ */
+public class RpcSocket {
+
+ // Constants
+ public static final int TIMEOUT = 2000;
+ public static final int QUEUE_SIZE = 10;
+ public static final int NUM_RETRIES = 3;
+ private static final Logger log = LoggerFactory.getLogger(RpcSocket.class);
+
+ private ZMQ.Socket socket;
+ private ZMQ.Poller poller;
+ private String address;
+ private SocketState state;
+ private long sendTime;
+ private int retriesLeft;
+ private LinkedBlockingQueue<MessageWrapper> inQueue;
+
+
+ public RpcSocket(String address, ZMQ.Poller poller) {
+ this.socket = null;
+ this.state = new IdleSocketState();
+ this.sendTime = -1;
+ this.retriesLeft = NUM_RETRIES;
+ this.inQueue = new LinkedBlockingQueue<MessageWrapper>(QUEUE_SIZE);
+ this.address = address;
+ this.poller = poller;
+ createSocket();
+ }
+
+ public ZMQ.Socket getSocket() {
+ return socket;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public int getRetriesLeft() {
+ return retriesLeft;
+ }
+
+ public void setRetriesLeft(int retriesLeft) {
+ this.retriesLeft = retriesLeft;
+ }
+
+ public SocketState getState() {
+ return state;
+ }
+
+ public void setState(SocketState state) {
+ this.state = state;
+ }
+
+ public int getQueueSize() {
+ return inQueue.size();
+ }
+
+ public MessageWrapper removeCurrentRequest() {
+ return inQueue.poll();
+ }
+
+ public boolean hasTimedOut() {
+ return (System.currentTimeMillis() - sendTime > RpcSocket.TIMEOUT);
+ }
+
+ public void send(MessageWrapper request) throws TimeoutException {
+ try {
+ boolean success = inQueue.offer(request, TIMEOUT, TimeUnit.MILLISECONDS);
+ if (!success) {
+ throw new TimeoutException("send :: Queue is full");
+ }
+ process();
+ }
+ catch (InterruptedException e) {
+ log.error("send : Thread interrupted while attempting to add request to inQueue", e);
+ }
+ }
+
+ public MessageWrapper receive() {
+ Message response = parseMessage();
+ MessageWrapper messageWrapper = inQueue.poll(); //remove the message from queue
+ MessageWrapper responseMessageWrapper = new MessageWrapper(response, messageWrapper.getReceiveSocket());
+
+ state = new IdleSocketState();
+ retriesLeft = NUM_RETRIES;
+ return responseMessageWrapper;
+ }
+
+ public void process() {
+ if (getQueueSize() > 0) //process if there's message in the queue
+ state.process(this);
+ }
+
+ // Called by IdleSocketState & BusySocketState
+ public void sendMessage() {
+ //Get the message from queue without removing it. For retries
+ MessageWrapper messageWrapper = inQueue.peek();
+ if (messageWrapper != null) {
+ Message message = messageWrapper.getMessage();
+ try {
+ socket.send(Message.serialize(message));
+ }
+ catch (IOException e) {
+ log.debug("Message send failed [{}]", message);
+ log.debug("Exception [{}]", e);
+ }
+ sendTime = System.currentTimeMillis();
+ }
+ }
+
+ public Message parseMessage() {
+ Message parsedMessage = null;
+ byte[] bytes = socket.recv();
+ log.debug("Received bytes:[{}]", bytes.length);
+ try {
+ parsedMessage = (Message)Message.deserialize(bytes);
+ }
+ catch (IOException|ClassNotFoundException e) {
+ log.debug("parseMessage : Deserializing received bytes failed", e);
+ }
+
+ return parsedMessage;
+ }
+
+ public void recycleSocket() {
+ close();
+ }
+
+ public void close() {
+ socket.setLinger(10);
+ socket.close();
+ }
+
+ private void createSocket() {
+ socket = Context.getInstance().getZmqContext().socket(ZMQ.REQ);
+ socket.connect(address);
+ poller.register(socket, ZMQ.Poller.POLLIN);
+ state = new IdleSocketState();
+ }
+
+
+ /**
+ * Represents the state of a {@link org.opendaylight.controller.sal.connector.remoterpc.RpcSocket}
+ */
+ public static interface SocketState {
+
+ /* The processing actions to be performed in this state
+ */
+ public void process(RpcSocket socket);
+ }
+
+ /**
+ * Represents the idle state of a {@link org.opendaylight.controller.sal.connector.remoterpc.RpcSocket}
+ */
+ public static class IdleSocketState implements SocketState {
+
+ @Override
+ public void process(RpcSocket socket) {
+ socket.sendMessage();
+ socket.setState(new BusySocketState());
+ socket.setRetriesLeft(socket.getRetriesLeft()-1);
+ }
+ }
+
+ /**
+ * Represents the busy state of a {@link org.opendaylight.controller.sal.connector.remoterpc.RpcSocket}
+ */
+ public static class BusySocketState implements SocketState {
+
+ private static Logger log = LoggerFactory.getLogger(BusySocketState.class);
+
+ @Override
+ public void process(RpcSocket socket) {
+ if (socket.hasTimedOut()) {
+ if (socket.getRetriesLeft() > 0) {
+ log.debug("process : Request timed out, retrying now...");
+ socket.sendMessage();
+ socket.setRetriesLeft(socket.getRetriesLeft() - 1);
+ }
+ else {
+ // No more retries for current request, so stop processing the current request
+ MessageWrapper message = socket.removeCurrentRequest();
+ if (message != null) {
+ log.error("Unable to process rpc request [{}]", message);
+ socket.setState(new IdleSocketState());
+ socket.setRetriesLeft(NUM_RETRIES);
+ }
+ }
+ }
+ // Else no timeout, so allow processing to continue
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+
+import static com.google.common.base.Preconditions.*;
+
+/**
+ * Main server thread for sending requests.
+ */
+public class Sender implements Runnable{
+
+ private final static Logger _logger = LoggerFactory.getLogger(Sender.class);
+ private final Client client;
+
+
+
+
+ public Sender(Client client) {
+ super();
+ this.client = client;
+ }
+
+@Override
+ public void run() {
+ _logger.info("Starting...");
+
+ try (SocketManager socketManager = new SocketManager()){
+ while (!Thread.currentThread().isInterrupted()) {
+
+ //read incoming messages from blocking queue
+ MessageWrapper request = pollForRequest();
+
+ if (request != null) {
+ processRequest(socketManager, request);
+ }
+
+ flushSockets(socketManager);
+ pollForResponse(socketManager);
+ processResponse(socketManager);
+
+ }
+ } catch(Exception t){
+ _logger.error("Exception: [{}]", t);
+ _logger.error("Stopping...");
+ }
+ }
+
+ private void processResponse(SocketManager socketManager) {
+ for (int i = 0; i < socketManager.getPoller().getSize(); i++) {
+ // If any sockets get a response, process it
+ if (socketManager.getPoller().pollin(i)) {
+ Optional<RpcSocket> socket = socketManager.getManagedSocketFor(
+ socketManager.getPoller().getItem(i).getSocket());
+
+ checkState(socket.isPresent(), "Managed socket not found");
+
+ MessageWrapper response = socket.get().receive();
+ _logger.debug("Received rpc response [{}]", response.getMessage());
+
+ //TODO: handle exception and introduce timeout on receiver side
+ try {
+ response.getReceiveSocket().send(Message.serialize(response.getMessage()));
+ } catch (IOException e) {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ }
+ }
+ }
+ }
+
+ private void processRequest(SocketManager socketManager, MessageWrapper request) throws TimeoutException {
+
+ if ((request.getMessage() == null) ||
+ (request.getMessage().getRecipient() == null)) {
+ //invalid message. log and drop
+ _logger.error("Invalid request [{}]", request);
+ return;
+ }
+
+ RpcSocket socket =
+ socketManager.getManagedSocket(request.getMessage().getRecipient());
+
+ socket.send(request);
+ }
+
+ private void flushSockets(SocketManager socketManager){
+ for (RpcSocket socket : socketManager.getManagedSockets()){
+ socket.process();
+ }
+ }
+
+ private MessageWrapper pollForRequest(){
+ return client.getRequestQueue().poll();
+ }
+
+ private void pollForResponse(SocketManager socketManager){
+ try{
+ socketManager.getPoller().poll(10); //poll every 10ms
+ }catch (Throwable t) { /*Ignore and continue*/ }
+ }
+}
+
+
+/*
+SCALA
+
+package org.opendaylight.controller.sal.connector.remoterpc
+
+ import org.slf4j.{LoggerFactory, Logger}
+ import scala.collection.JavaConverters._
+ import scala.Some
+ import org.opendaylight.controller.sal.connector.remoterpc.dto.{MessageWrapper, Message}
+*/
+/**
+ * Main server thread for sending requests. This does not maintain any state. If the
+ * thread dies, it will be restarted
+ */
+/*class Sender extends Runnable {
+ private val _logger: Logger = LoggerFactory.getLogger(Sender.this.getClass())
+
+ override def run = {
+ _logger.info("Sender starting...")
+ val socketManager = new SocketManager()
+
+ try {
+ while (!Thread.currentThread().isInterrupted) {
+ //read incoming messages from blocking queue
+ val request: MessageWrapper = Client.requestQueue.poll()
+
+ if (request != null) {
+ if ((request.message != null) &&
+ (request.message.getRecipient != null)) {
+
+ val socket = socketManager.getManagedSocket(request.message.getRecipient)
+ socket.send(request)
+ } else {
+ //invalid message. log and drop
+ _logger.error("Invalid request [{}]", request)
+ }
+ }
+
+ socketManager.getManagedSockets().asScala.map(s => s.process)
+
+ // Poll all sockets for responses every 1 sec
+ poll(socketManager)
+
+ // If any sockets get a response, process it
+ for (i <- 0 until socketManager.poller.getSize) {
+ if (socketManager.poller.pollin(i)) {
+ val socket = socketManager.getManagedSocketFor(socketManager.poller.getItem(i).getSocket)
+
+ socket match {
+ case None => //{
+ _logger.error("Could not find a managed socket for zmq socket")
+ throw new IllegalStateException("Could not find a managed socket for zmq socket")
+ //}
+ case Some(s) => {
+ val response = s.receive()
+ _logger.debug("Received rpc response [{}]", response.message)
+ response.receiveSocket.send(Message.serialize(response.message))
+ }
+ }
+ }
+ }
+
+ }
+ } catch{
+ case e:Exception => {
+ _logger.debug("Sender stopping due to exception")
+ e.printStackTrace()
+ }
+ } finally {
+ socketManager.stop
+ }
+ }
+
+ def poll(socketManager:SocketManager) = {
+ try{
+ socketManager.poller.poll(10)
+ }catch{
+ case t:Throwable => //ignore and continue
+ }
+ }
+}
+
+
+// def newThread(r: Runnable): Thread = {
+// val t = new RequestHandler()
+// t.setUncaughtExceptionHandler(new RequestProcessorExceptionHandler)
+// t
+// }
+
+
+
+/**
+ * Restarts the request processing server in the event of unforeseen exceptions
+ */
+//private class RequestProcessorExceptionHandler extends UncaughtExceptionHandler {
+// def uncaughtException(t: Thread, e: Throwable) = {
+// _logger.error("Exception caught during request processing [{}]", e)
+// _logger.info("Restarting request processor server...")
+// RequestProcessor.start()
+// }
--- /dev/null
+/*
+ * 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
+import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message.MessageType;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * ZeroMq based implementation of RpcRouter TODO: 1. Make rpc request handling
+ * async and non-blocking. Note zmq socket is not thread safe 2. Read properties
+ * from config file using existing(?) ODL properties framework
+ */
+public class ServerImpl implements RemoteRpcServer, RouteChangeListener<String, Set> {
+
+ private Logger _logger = LoggerFactory.getLogger(ServerImpl.class);
+
+ private ExecutorService serverPool;
+
+ // private RoutingTable<RpcRouter.RouteIdentifier, String> routingTable;
+ private RoutingTableProvider routingTable;
+ private Set<QName> remoteServices;
+ private ProviderSession brokerSession;
+ private ZMQ.Context context;
+ private ZMQ.Socket replySocket;
+
+ private final RpcListener listener = new RpcListener();
+
+ private final String localUri = Context.getInstance().getLocalUri();
+
+ private final int rpcPort;
+
+ private RpcImplementation client;
+
+ public RpcImplementation getClient() {
+ return client;
+ }
+
+ public void setClient(RpcImplementation client) {
+ this.client = client;
+ }
+
+ // Prevent instantiation
+ public ServerImpl(int rpcPort) {
+ this.rpcPort = rpcPort;
+ }
+
+ public void setBrokerSession(ProviderSession session) {
+ this.brokerSession = session;
+ }
+
+ public ExecutorService getServerPool() {
+ return serverPool;
+ }
+
+ public void setServerPool(ExecutorService serverPool) {
+ this.serverPool = serverPool;
+ }
+
+ public void start() {
+ context = ZMQ.context(1);
+ serverPool = Executors.newSingleThreadExecutor();
+ remoteServices = new HashSet<QName>();
+
+ // Start listening rpc requests
+ serverPool.execute(receive());
+
+ brokerSession.addRpcRegistrationListener(listener);
+ // routingTable.registerRouteChangeListener(routeChangeListener);
+
+ Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
+ for (QName rpc : currentlySupported) {
+ listener.onRpcImplementationAdded(rpc);
+ }
+
+ _logger.debug("RPC Server started [{}]", localUri);
+ }
+
+ public void stop() {
+ // TODO: un-subscribe
+
+ // if (context != null)
+ // context.term();
+ //
+ // _logger.debug("ZMQ Context is terminated.");
+
+ if (serverPool != null)
+ serverPool.shutdown();
+
+ _logger.debug("Thread pool is closed.");
+ }
+
+ private Runnable receive() {
+ return new Runnable() {
+ public void run() {
+
+ // Bind to RPC reply socket
+ replySocket = context.socket(ZMQ.REP);
+ replySocket.bind("tcp://*:" + Context.getInstance().getRpcPort());
+
+ // Poller enables listening on multiple sockets using a single
+ // thread
+ ZMQ.Poller poller = new ZMQ.Poller(1);
+ poller.register(replySocket, ZMQ.Poller.POLLIN);
+ try {
+ // TODO: Add code to restart the thread after exception
+ while (!Thread.currentThread().isInterrupted()) {
+
+ poller.poll();
+
+ if (poller.pollin(0)) {
+ handleRpcCall();
+ }
+ }
+ } catch (Exception e) {
+ // log and continue
+ _logger.error("Unhandled exception [{}]", e);
+ } finally {
+ poller.unregister(replySocket);
+ replySocket.close();
+ }
+
+ }
+ };
+ }
+
+ /**
+ * @throws InterruptedException
+ * @throws ExecutionException
+ */
+ private void handleRpcCall() {
+
+ Message request = parseMessage(replySocket);
+
+ _logger.debug("Received rpc request [{}]", request);
+
+ // Call broker to process the message then reply
+ Future<RpcResult<CompositeNode>> rpc = null;
+ RpcResult<CompositeNode> result = null;
+ try {
+ rpc = brokerSession.rpc((QName) request.getRoute().getType(),
+ XmlUtils.xmlToCompositeNode((String) request.getPayload()));
+
+ result = (rpc != null) ? rpc.get() : null;
+
+ } catch (Exception e) {
+ _logger.debug("Broker threw [{}]", e);
+ }
+
+ CompositeNode payload = (result != null) ? result.getResult() : null;
+
+ Message response = new Message.MessageBuilder().type(MessageType.RESPONSE).sender(localUri)
+ .route(request.getRoute()).payload(XmlUtils.compositeNodeToXml(payload)).build();
+
+ _logger.debug("Sending rpc response [{}]", response);
+
+ try {
+ replySocket.send(Message.serialize(response));
+ } catch (Exception e) {
+ _logger.debug("rpc response send failed for message [{}]", response);
+ _logger.debug("{}", e);
+ }
+
+ }
+
+ /**
+ * @param socket
+ * @return
+ */
+ private Message parseMessage(ZMQ.Socket socket) {
+
+ Message msg = null;
+ try {
+ byte[] bytes = socket.recv();
+ _logger.debug("Received bytes:[{}]", bytes.length);
+ msg = (Message) Message.deserialize(bytes);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ return msg;
+ }
+
+ @Override
+ public void onRouteUpdated(String key, Set values) {
+ RouteIdentifierImpl rId = new RouteIdentifierImpl();
+ try {
+ _logger.debug("Updating key/value {}-{}", key, values);
+ brokerSession.addRpcImplementation((QName) rId.fromString(key).getType(), client);
+
+ } catch (Exception e) {
+ _logger.info("Route update failed {}", e);
+ }
+ }
+
+ @Override
+ public void onRouteDeleted(String key) {
+ // TODO: Broker session needs to be updated to support this
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Listener for rpc registrations
+ */
+ private class RpcListener implements RpcRegistrationListener {
+
+
+
+ @Override
+ public void onRpcImplementationAdded(QName name) {
+
+ // if the service name exists in the set, this notice
+ // has bounced back from the broker. It should be ignored
+ if (remoteServices.contains(name))
+ return;
+
+ _logger.debug("Adding registration for [{}]", name);
+ RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+ routeId.setType(name);
+
+ try {
+ routingTable.getRoutingTable().get().addGlobalRoute(routeId.toString(), localUri);
+ _logger.debug("Route added [{}-{}]", name, localUri);
+ } catch (RoutingTableException | SystemException e) {
+ // TODO: This can be thrown when route already exists in the
+ // table. Broker
+ // needs to handle this.
+ _logger.error("Unhandled exception while adding global route to routing table [{}]", e);
+
+ }
+ }
+
+ @Override
+ public void onRpcImplementationRemoved(QName name) {
+
+ _logger.debug("Removing registration for [{}]", name);
+ RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+ routeId.setType(name);
+
+ try {
+ routingTable.getRoutingTable().get().removeGlobalRoute(routeId.toString());
+ } catch (RoutingTableException | SystemException e) {
+ _logger.error("Route delete failed {}", e);
+ }
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ stop();
+ }
+
+ public void setRoutingTableProvider(RoutingTableProvider provider) {
+ this.routingTable = provider;
+ }
+
+}
--- /dev/null
+/*
+ * 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+import java.net.UnknownHostException;
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+/**
+ * Manages creation of {@link RpcSocket} and their registration with {@link ZMQ.Poller}
+ */
+public class SocketManager implements AutoCloseable{
+ private static final Logger log = LoggerFactory.getLogger(SocketManager.class);
+
+ /*
+ * RpcSockets mapped by network address its connected to
+ */
+ private ConcurrentHashMap<String, RpcSocket> managedSockets = new ConcurrentHashMap<String, RpcSocket>();
+
+ private ZMQ.Poller _poller = new ZMQ.Poller(2); //randomly selected size. Poller grows automatically
+
+ /**
+ * Returns a {@link RpcSocket} for the given address
+ * @param address network address with port eg: 10.199.199.20:5554
+ * @return
+ */
+ public RpcSocket getManagedSocket(String address) throws IllegalArgumentException {
+ //Precondition
+ if (!address.matches("(tcp://)(.*)(:)(\\d*)")) {
+ throw new IllegalArgumentException("Address must of format 'tcp://<ip address>:<port>' but is " + address);
+ }
+
+ if (!managedSockets.containsKey(address)) {
+ log.debug("{} Creating new socket for {}", Thread.currentThread().getName());
+ RpcSocket socket = new RpcSocket(address, _poller);
+ managedSockets.put(address, socket);
+ }
+
+ return managedSockets.get(address);
+ }
+
+ /**
+ * Returns a {@link RpcSocket} for the given {@link ZMQ.Socket}
+ * @param socket
+ * @return
+ */
+ public Optional<RpcSocket> getManagedSocketFor(ZMQ.Socket socket) {
+ for (RpcSocket rpcSocket : managedSockets.values()) {
+ if (rpcSocket.getSocket().equals(socket)) {
+ return Optional.of(rpcSocket);
+ }
+ }
+ return Optional.absent();
+ }
+
+ /**
+ * Return a collection of all managed sockets
+ * @return
+ */
+ public Collection<RpcSocket> getManagedSockets() {
+ return managedSockets.values();
+ }
+
+ /**
+ * Returns the {@link ZMQ.Poller}
+ * @return
+ */
+ public ZMQ.Poller getPoller() {
+ return _poller;
+ }
+
+ /**
+ * This should be called when stopping the server to close all the sockets
+ * @return
+ */
+ @Override
+ public void close() throws Exception {
+ log.debug("Stopping...");
+ for (RpcSocket socket : managedSockets.values()) {
+ socket.close();
+ }
+ managedSockets.clear();
+ log.debug("Stopped");
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.zeromq.ZMQ;
+
+import java.util.UUID;
+
+/**
+ *
+ */
+public class SocketPair implements AutoCloseable{
+ private ZMQ.Socket sender;
+ private ZMQ.Socket receiver;
+
+ private static final String INPROC_PREFIX = "inproc://";
+
+ public SocketPair(){
+ String address = new StringBuilder(INPROC_PREFIX)
+ .append(UUID.randomUUID())
+ .toString();
+
+ receiver = Context.getInstance().getZmqContext().socket(ZMQ.PAIR);
+ receiver.bind(address);
+
+ sender = Context.getInstance().getZmqContext().socket(ZMQ.PAIR);
+ sender.connect(address);
+ }
+
+ public ZMQ.Socket getSender(){
+ return this.sender;
+ }
+
+ public ZMQ.Socket getReceiver(){
+ return this.receiver;
+ }
+
+ @Override
+ public void close() throws Exception {
+ sender.close();
+ receiver.close();
+ }
+}
--- /dev/null
+/*
+ * 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.connector.remoterpc.dto;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.*;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class CompositeNodeImpl implements CompositeNode, Serializable {
+
+ private QName key;
+ private List<Node<?>> children;
+
+ @Override
+ public List<Node<?>> getChildren() {
+ return children;
+ }
+
+ @Override
+ public List<CompositeNode> getCompositesByName(QName children) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<CompositeNode> getCompositesByName(String children) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public List<SimpleNode<?>> getSimpleNodesByName(QName children) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public List<SimpleNode<?>> getSimpleNodesByName(String children) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public CompositeNode getFirstCompositeByName(QName container) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public SimpleNode<?> getFirstSimpleByName(QName leaf) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public MutableCompositeNode asMutable() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public QName getKey() {
+ return key; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public List<Node<?>> setValue(List<Node<?>> value) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public int size() {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public List<Node<?>> get(Object key) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public List<Node<?>> put(QName key, List<Node<?>> value) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public List<Node<?>> remove(Object key) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void putAll(Map<? extends QName, ? extends List<Node<?>>> m) {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void clear() {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public Set<QName> keySet() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public Collection<List<Node<?>>> values() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public Set<Entry<QName, List<Node<?>>>> entrySet() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public QName getNodeType() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public CompositeNode getParent() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public List<Node<?>> getValue() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public ModifyAction getModificationAction() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.sal.connector.remoterpc.router.zeromq;
+package org.opendaylight.controller.sal.connector.remoterpc.dto;
-
-import org.codehaus.jackson.map.ObjectMapper;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import java.io.*;
ANNOUNCE((byte) 0), //TODO: Remove announce, add rpc registration and deregistration
HEARTBEAT((byte) 1),
REQUEST((byte) 2),
- RESPONSE((byte) 3);
+ RESPONSE((byte) 3),
+ ERROR((byte)4);
private final byte type;
private MessageType type;
private String sender;
+ private String recipient;
private RpcRouter.RouteIdentifier route;
private Object payload;
this.payload = payload;
}
+ public String getRecipient() {
+ return recipient;
+ }
+
+ public void setRecipient(String recipient) {
+ this.recipient = recipient;
+ }
@Override
public String toString() {
return "Message{" +
"type=" + type +
", sender='" + sender + '\'' +
+ ", recipient='" + recipient + '\'' +
", route=" + route +
", payload=" + payload +
'}';
return o.readObject();
}
- public static byte[] toJsonBytes(Message m) throws IOException {
- ObjectMapper o = new ObjectMapper();
- return o.writeValueAsBytes(m);
- }
-
- public static Message fromJsonBytes(byte [] bytes) throws IOException {
-
- ObjectMapper o = new ObjectMapper();
- return o.readValue(bytes, Message.class);
- }
-
public static class Response extends Message implements RpcRouter.RpcReply {
private ResponseCode code; // response code
return this;
}
+ public MessageBuilder recipient(String recipient){
+ message.setRecipient(recipient);
+ return this;
+ }
+
public MessageBuilder route(RpcRouter.RouteIdentifier route){
message.setRoute(route);
return this;
--- /dev/null
+/*
+ * 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.connector.remoterpc.dto;
+
+import org.zeromq.ZMQ;
+
+/**
+ * A class encapsulating {@link Message} and the {@link ZMQ.Socket} over which it is transmitted
+ */
+public class MessageWrapper {
+
+ private Message _message;
+ private ZMQ.Socket _receiveSocket;
+
+ public MessageWrapper(Message message, ZMQ.Socket receiveSocket) {
+ this._message = message;
+ this._receiveSocket = receiveSocket;
+ }
+
+ public Message getMessage() {
+ return _message;
+ }
+
+ public ZMQ.Socket getReceiveSocket() {
+ return _receiveSocket;
+ }
+}
* 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.connector.remoterpc.router.zeromq;
+package org.opendaylight.controller.sal.connector.remoterpc.dto;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import java.io.Serializable;
+import java.net.URI;
-/**
- * User: abhishk2
- */
public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>,Serializable {
+ transient ObjectMapper mapper = new ObjectMapper();
+
private QName context;
private QName type;
private InstanceIdentifier route;
@Override
public String toString() {
- return "RouteIdentifierImpl{" +
- "context=" + context +
- ", type=" + type +
- ", route=" + route +
- '}';
+ try {
+ return mapper.writeValueAsString(this);
+ } catch (Throwable e) {
+ //do nothing
+ }
+
+ return super.toString();
+ }
+
+ public RpcRouter.RouteIdentifier fromString(String input)
+ throws Exception {
+
+ JsonNode root = mapper.readTree(input);
+ this.context = parseQName(root.get("context"));
+ this.type = parseQName(root.get("type"));
+
+ return this;
+ }
+
+ private QName parseQName(JsonNode node){
+ if (node == null) return null;
+
+ String namespace = (node.get("namespace") != null) ?
+ node.get("namespace").asText() : "";
+
+ String localName = (node.get("localName") != null) ?
+ node.get("localName").asText() : "";
+
+ URI uri = URI.create(namespace);
+ return new QName(uri, localName);
}
}
* 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.connector.remoterpc.router.zeromq;
+package org.opendaylight.controller.sal.connector.remoterpc.dto;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.yangtools.yang.common.QName;
--- /dev/null
+package org.opendaylight.controller.sal.connector.remoterpc.util;
+
+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.data.impl.NodeUtils;
+import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayInputStream;
+import java.io.StringWriter;
+
+public class XmlUtils {
+
+ private static final Logger _logger = LoggerFactory.getLogger(XmlUtils.class);
+
+ public static String compositeNodeToXml(CompositeNode cNode){
+ if (cNode == null) return new String();
+
+ Document domTree = NodeUtils.buildShadowDomTree(cNode);
+ StringWriter writer = new StringWriter();
+ try {
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer transformer = tf.newTransformer();
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ transformer.transform(new DOMSource(domTree), new StreamResult(writer));
+ } catch (TransformerException e) {
+ _logger.error("Error during translation of Document to OutputStream", e);
+ }
+
+ return writer.toString();
+ }
+
+ public static CompositeNode xmlToCompositeNode(String xml){
+ if (xml==null || xml.length()==0) return null;
+
+ Node<?> dataTree;
+ try {
+ dataTree = XmlTreeBuilder.buildDataTree(new ByteArrayInputStream(xml.getBytes()));
+ } catch (XMLStreamException e) {
+ _logger.error("Error during building data tree from XML", e);
+ return null;
+ }
+ if (dataTree == null) {
+ _logger.error("data tree is null");
+ return null;
+ }
+ if (dataTree instanceof SimpleNode) {
+ _logger.error("RPC XML was resolved as SimpleNode");
+ return null;
+ }
+ return (CompositeNode) dataTree;
+ }
+}
--- /dev/null
+/*
+ * 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.connector.remoterpc
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.common.{RpcError, RpcResult, QName}
+import org.opendaylight.controller.sal.core.api.RpcImplementation
+import java.util
+import java.util.{UUID, Collections}
+import org.zeromq.ZMQ
+import org.opendaylight.controller.sal.common.util.{RpcErrors, Rpcs}
+import org.slf4j.LoggerFactory
+import org.opendaylight.controller.sal.connector.remoterpc.dto.{MessageWrapper, RouteIdentifierImpl, Message}
+import Message.MessageType
+import java.util.concurrent._
+import java.lang.InterruptedException
+
+
+/**
+ * An implementation of {@link RpcImplementation} that makes
+ * remote RPC calls
+ */
+class Client extends RemoteRpcClient {
+
+ private val _logger = LoggerFactory.getLogger(this.getClass);
+
+ val requestQueue = new LinkedBlockingQueue[MessageWrapper](100)
+ val pool: ExecutorService = Executors.newSingleThreadExecutor()
+ private val TIMEOUT = 5000 //in ms
+ var routingTableProvider: RoutingTableProvider = null
+
+
+ def getInstance = this
+
+
+ def setRoutingTableProvider(provider : RoutingTableProvider) = {
+ routingTableProvider = provider;
+ }
+
+ def getSupportedRpcs: util.Set[QName] = {
+ Collections.emptySet()
+ }
+
+ def invokeRpc(rpc: QName, input: CompositeNode): RpcResult[CompositeNode] = {
+
+ val routeId = new RouteIdentifierImpl()
+ routeId.setType(rpc)
+
+ //lookup address for the rpc request
+ val routingTable = routingTableProvider.getRoutingTable()
+ require( routingTable != null, "Routing table not found. Exiting" )
+
+ val addresses:util.Set[String] = routingTable.getRoutes(routeId.toString)
+ require(addresses != null, "Address not found for rpc " + rpc);
+ require(addresses.size() == 1) //its a global service.
+
+ val address = addresses.iterator().next()
+ require(address != null, "Address is null")
+
+ //create in-process "pair" socket and pass it to sender thread
+ //Sender replies on this when result is available
+ val inProcAddress = "inproc://" + UUID.randomUUID()
+ val receiver = Context.zmqContext.socket(ZMQ.PAIR)
+ receiver.bind(inProcAddress);
+
+ val sender = Context.zmqContext.socket(ZMQ.PAIR)
+ sender.connect(inProcAddress)
+
+ val requestMessage = new Message.MessageBuilder()
+ .`type`(MessageType.REQUEST)
+ //.sender("tcp://localhost:8081")
+ .recipient(address)
+ .route(routeId)
+ .payload(input)
+ .build()
+
+ _logger.debug("Queuing up request and expecting response on [{}]", inProcAddress)
+
+ val messageWrapper = new MessageWrapper(requestMessage, sender)
+ val errors = new util.ArrayList[RpcError]
+
+ try {
+ process(messageWrapper)
+ val response = parseMessage(receiver)
+
+ return Rpcs.getRpcResult(
+ true, response.getPayload.asInstanceOf[CompositeNode], Collections.emptySet())
+
+ } catch {
+ case e: Exception => {
+ errors.add(RpcErrors.getRpcError(null,null,null,null,e.getMessage,null,e.getCause))
+ return Rpcs.getRpcResult(false, null, errors)
+ }
+ } finally {
+ receiver.close();
+ sender.close();
+ }
+
+ }
+
+ /**
+ * Block on socket for reply
+ * @param receiver
+ * @return
+ */
+ private def parseMessage(receiver:ZMQ.Socket): Message = {
+ val bytes = receiver.recv()
+ return Message.deserialize(bytes).asInstanceOf[Message]
+ }
+
+ def start() = {
+ pool.execute(new Sender)
+ }
+
+ def process(msg: MessageWrapper) = {
+ _logger.debug("Processing message [{}]", msg)
+ val success = requestQueue.offer(msg, TIMEOUT, TimeUnit.MILLISECONDS)
+
+ if (!success) throw new TimeoutException("Queue is full");
+
+ }
+
+ def stop() = {
+ pool.shutdown() //intiate shutdown
+ _logger.debug("Client stopping...")
+ // Context.zmqContext.term();
+ // _logger.debug("ZMQ context terminated")
+
+ try {
+
+ if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
+ pool.shutdownNow();
+ if (!pool.awaitTermination(10, TimeUnit.SECONDS))
+ _logger.error("Client thread pool did not shut down");
+ }
+ } catch {
+ case ie:InterruptedException =>
+ // (Re-)Cancel if current thread also interrupted
+ pool.shutdownNow();
+ // Preserve interrupt status
+ Thread.currentThread().interrupt();
+ }
+ _logger.debug("Client stopped")
+ }
+
+ def close() = {
+ stop();
+ }
+}
--- /dev/null
+module odl-sal-dom-rpc-remote-cfg {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc";
+ prefix "rpc-cluster";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-dom {prefix dom;}
+
+ description
+ "Service definition for Binding Aware MD-SAL.";
+
+ revision "2013-10-28" {
+ description
+ "Initial revision";
+ }
+
+ identity remote-rpc-server {
+ base config:service-type;
+ config:java-class "org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcServer";
+ }
+
+ identity remote-rpc-client {
+ base config:service-type;
+ config:java-class "org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcClient";
+ }
+
+ identity remote-zeromq-rpc-server {
+ base config:module-type;
+ config:provided-service remote-rpc-server;
+ config:provided-service remote-rpc-client;
+ config:java-name-prefix ZeroMQServer;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case remote-zeromq-rpc-server {
+ when "/config:modules/config:module/config:type = 'remote-zeromq-rpc-server'";
+
+ container dom-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity dom:dom-broker-osgi-registry;
+ }
+ }
+ }
+
+ leaf port {
+ type uint16;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+
+import java.util.concurrent.TimeoutException;
+
+public class ClientTest {
+
+ Client client;
+
+ @Before
+ public void setup(){
+ client = new Client();
+ client.getRequestQueue().clear();
+ }
+
+ @Test
+ public void testStop() throws Exception {
+
+ }
+
+ @Test
+ public void testPool() throws Exception {
+
+ }
+
+ @Test
+ public void process_AddAMessage_ShouldAddToQueue() throws Exception {
+ client.process(getEmptyMessageWrapper());
+ Assert.assertEquals(1, client.getRequestQueue().size());
+ }
+
+ /**
+ * Queue size is 100. Adding 101 message should time out in 2 sec
+ * if server does not process it
+ * @throws Exception
+ */
+ @Test(expected = TimeoutException.class)
+ public void process_Add101Message_ShouldThrow() throws Exception {
+ for (int i=0;i<101;i++){
+ client.process(getEmptyMessageWrapper());
+ }
+ }
+
+ @Test
+ public void testStart() throws Exception {
+ }
+
+ private MessageWrapper getEmptyMessageWrapper(){
+ return new MessageWrapper(new Message(), null);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.codehaus.jackson.JsonParseException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+
+public class RouteIdentifierImplTest {
+
+ Logger _logger = LoggerFactory.getLogger(RouteIdentifierImplTest.class);
+
+ private final URI namespace = URI.create("http://cisco.com/example");
+ private final QName QNAME = new QName(namespace, "heartbeat");
+
+ @Test
+ public void testToString() throws Exception {
+ RouteIdentifierImpl rId = new RouteIdentifierImpl();
+ rId.setType(QNAME);
+
+ _logger.debug(rId.toString());
+
+ Assert.assertTrue(true);
+
+ }
+
+ @Test
+ public void testFromString() throws Exception {
+ RouteIdentifierImpl rId = new RouteIdentifierImpl();
+ rId.setType(QNAME);
+
+ _logger.debug("route: " + rId.fromString(rId.toString()));
+
+ Assert.assertTrue(true);
+ }
+
+ @Test(expected = JsonParseException.class)
+ public void testFromInvalidString() throws Exception {
+ String invalidInput = "aklhdgadfa;;;;;;;]]]]=]ag" ;
+ RouteIdentifierImpl rId = new RouteIdentifierImpl();
+ rId.fromString(invalidInput);
+
+ _logger.debug("" + rId);
+ Assert.assertTrue(true);
+ }
+}
--- /dev/null
+/*
+ * 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.connector.remoterpc;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.MessageWrapper;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.zeromq.ZMQ;
+
+import java.util.concurrent.TimeoutException;
+
+import static org.mockito.Mockito.doNothing;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(RpcSocket.class)
+public class RpcSocketTest {
+ RpcSocket rpcSocket = new RpcSocket("tcp://localhost:5554", new ZMQ.Poller(1));
+ RpcSocket spy = PowerMockito.spy(rpcSocket);
+
+ @Test
+ public void testCreateSocket() throws Exception {
+ Assert.assertEquals("tcp://localhost:5554", spy.getAddress());
+ Assert.assertEquals(ZMQ.REQ, spy.getSocket().getType());
+ }
+
+ @Test(expected = TimeoutException.class)
+ public void send_WhenQueueGetsFull_ShouldThrow() throws Exception {
+
+ doNothing().when(spy).process();
+
+ //10 is queue size
+ for (int i=0;i<10;i++){
+ spy.send(getEmptyMessageWrapper());
+ }
+
+ //sending 11th message should throw
+ spy.send(getEmptyMessageWrapper());
+ }
+
+ @Test
+ public void testHasTimedOut() throws Exception {
+ spy.send(getEmptyMessageWrapper());
+ Assert.assertFalse(spy.hasTimedOut());
+ Thread.sleep(1000);
+ Assert.assertFalse(spy.hasTimedOut());
+ Thread.sleep(1000);
+ Assert.assertTrue(spy.hasTimedOut());
+ }
+
+ @Test
+ public void testProcess() throws Exception {
+ PowerMockito.doNothing().when(spy, "sendMessage");
+ spy.send(getEmptyMessageWrapper());
+
+ //Next message should get queued
+ spy.send(getEmptyMessageWrapper());
+
+ //queue size should be 2
+ Assert.assertEquals(2, spy.getQueueSize());
+
+
+ spy.process();
+ //sleep for 2 secs (timeout)
+ //message send would be retried
+ Thread.sleep(2000);
+ spy.process();
+ Thread.sleep(2000);
+ spy.process();
+ Thread.sleep(2000);
+ spy.process(); //retry fails, next message will get picked up
+ Assert.assertEquals(1, spy.getQueueSize());
+ }
+
+ @Test
+ public void testProcessStateTransitions() throws Exception {
+ PowerMockito.doNothing().when(spy, "sendMessage");
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+ spy.send(getEmptyMessageWrapper());
+ Assert.assertEquals(1, spy.getQueueSize());
+ Thread.sleep(200);
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+ Thread.sleep(1800);
+
+ //1st timeout, 2nd try
+ spy.process();
+ Thread.sleep(200);
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+ Thread.sleep(1800);
+
+ //2nd timeout, 3rd try
+ spy.process();
+ Thread.sleep(200);
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+ Thread.sleep(1800);
+
+ //3rd timeout, no more tries => remove
+ spy.process();
+ Thread.sleep(200);
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+ Assert.assertEquals(0, spy.getQueueSize());
+ }
+
+ @Test
+ public void testParseMessage() throws Exception {
+ // Write an integration test for parseMessage
+ }
+
+ @Test
+ public void testRecycleSocket() throws Exception {
+ // This will need to be updated in the future...for now, recycleSocket() calls close()
+ Assert.assertTrue(spy.getSocket().base().check_tag());
+ spy.close();
+ Assert.assertEquals(10, spy.getSocket().getLinger());
+ Assert.assertFalse(spy.getSocket().base().check_tag());
+ }
+
+ @Test
+ public void testClose() throws Exception {
+ Assert.assertTrue(spy.getSocket().base().check_tag());
+ spy.close();
+ Assert.assertEquals(10, spy.getSocket().getLinger());
+ Assert.assertFalse(spy.getSocket().base().check_tag());
+ }
+
+ @Test
+ public void testReceive() throws Exception {
+ PowerMockito.doReturn(null).when(spy, "parseMessage");
+ PowerMockito.doNothing().when(spy, "process");
+ spy.send(getEmptyMessageWrapper());
+
+ //There should be 1 message waiting in the queue
+ Assert.assertEquals(1, spy.getQueueSize());
+
+ spy.receive();
+ //This should complete message processing
+ //The message should be removed from the queue
+ Assert.assertEquals(0, spy.getQueueSize());
+ Assert.assertEquals(RpcSocket.NUM_RETRIES, spy.getRetriesLeft());
+
+ }
+
+ @Test
+ public void testReceiveStateTransitions() throws Exception {
+ PowerMockito.doReturn(null).when(spy, "parseMessage");
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+ spy.send(getEmptyMessageWrapper());
+
+ //There should be 1 message waiting in the queue
+ Assert.assertEquals(1, spy.getQueueSize());
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+
+ spy.receive();
+ //This should complete message processing
+ //The message should be removed from the queue
+ Assert.assertEquals(0, spy.getQueueSize());
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+ }
+
+ private MessageWrapper getEmptyMessageWrapper(){
+ return new MessageWrapper(new Message(), null);
+ }
+
+ @Test
+ public void testProcessReceiveSequence() throws Exception {
+ PowerMockito.doNothing().when(spy, "sendMessage");
+ PowerMockito.doReturn(null).when(spy, "parseMessage");
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+ spy.send(getEmptyMessageWrapper());
+ spy.send(getEmptyMessageWrapper());
+ Assert.assertEquals(2, spy.getQueueSize());
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+
+
+ Thread.sleep(2000);
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+ spy.receive();
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+ Assert.assertEquals(1, spy.getQueueSize());
+
+ spy.process();
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.BusySocketState);
+ spy.receive();
+ Assert.assertTrue(spy.getState() instanceof RpcSocket.IdleSocketState);
+ Assert.assertEquals(0, spy.getQueueSize());
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connector.remoterpc;
+
+import org.junit.Test;
+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.data.impl.NodeUtils;
+import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.StringWriter;
+
+public class SerilizationTest {
+
+ private static final Logger _logger = LoggerFactory.getLogger(SerilizationTest.class);
+
+ public void fromXml() {
+ }
+
+ @Test
+ public void toXml() throws FileNotFoundException {
+
+ InputStream xmlStream = SerilizationTest.class.getResourceAsStream("/FourSimpleChildren.xml");
+ StringWriter writer = new StringWriter();
+
+ CompositeNode data = loadCompositeNode(xmlStream);
+ Document domTree = NodeUtils.buildShadowDomTree(data);
+ try {
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer transformer = tf.newTransformer();
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ //transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+ //transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ //transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ //transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+ transformer.transform(new DOMSource(domTree), new StreamResult(writer));
+ } catch (TransformerException e) {
+ _logger.error("Error during translation of Document to OutputStream", e);
+ }
+
+ _logger.info("Parsed xml [{}]", writer.toString());
+ }
+
+ //Note to self: Stolen from TestUtils
+ ///Users/alefan/odl/controller4/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
+ // Figure out how to include TestUtils through pom ...was getting errors
+ private CompositeNode loadCompositeNode(InputStream xmlInputStream) throws FileNotFoundException {
+ if (xmlInputStream == null) {
+ throw new IllegalArgumentException();
+ }
+ Node<?> dataTree;
+ try {
+ dataTree = XmlTreeBuilder.buildDataTree(xmlInputStream);
+ } catch (XMLStreamException e) {
+ _logger.error("Error during building data tree from XML", e);
+ return null;
+ }
+ if (dataTree == null) {
+ _logger.error("data tree is null");
+ return null;
+ }
+ if (dataTree instanceof SimpleNode) {
+ _logger.error("RPC XML was resolved as SimpleNode");
+ return null;
+ }
+ return (CompositeNode) dataTree;
+ }
+}
--- /dev/null
+/*
+ * 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.connector.remoterpc;
+
+import com.google.common.base.Optional;
+import junit.framework.Assert;
+import org.junit.After;
+import org.junit.Before;
+import org.zeromq.ZMQ;
+import org.opendaylight.controller.sal.connector.remoterpc.SocketManager;
+import org.opendaylight.controller.sal.connector.remoterpc.RpcSocket;
+import org.opendaylight.controller.sal.connector.remoterpc.Context;
+import org.junit.Test;
+
+public class SocketManagerTest {
+
+ SocketManager manager;
+
+ @Before
+ public void setup(){
+ manager = new SocketManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ manager.close();
+ }
+
+ @Test
+ public void getManagedSockets_When2NewAdded_ShouldContain2() throws Exception {
+
+ //Prepare data
+ manager.getManagedSocket("tcp://localhost:5554");
+ manager.getManagedSocket("tcp://localhost:5555");
+
+ Assert.assertTrue( 2 == manager.getManagedSockets().size());
+ }
+
+ @Test
+ public void getManagedSockets_When2NewAddedAnd1Existing_ShouldContain2() throws Exception {
+
+ //Prepare data
+ manager.getManagedSocket("tcp://localhost:5554");
+ manager.getManagedSocket("tcp://localhost:5555");
+ manager.getManagedSocket("tcp://localhost:5554"); //ask for the first one
+
+ Assert.assertTrue( 2 == manager.getManagedSockets().size());
+ }
+
+ @Test
+ public void getManagedSocket_WhenPassedAValidAddress_ShouldReturnARpcSocket() throws Exception {
+ String testAddress = "tcp://localhost:5554";
+ RpcSocket rpcSocket = manager.getManagedSocket(testAddress);
+ Assert.assertEquals(testAddress, rpcSocket.getAddress());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void getManagedSocket_WhenPassedInvalidHostAddress_ShouldThrow() throws Exception {
+ String testAddress = "tcp://nonexistenthost:5554";
+ RpcSocket rpcSocket = manager.getManagedSocket(testAddress);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void getManagedSocket_WhenPassedInvalidAddress_ShouldThrow() throws Exception {
+ String testAddress = "xxx";
+ RpcSocket rpcSocket = manager.getManagedSocket(testAddress);
+ }
+
+ @Test
+ public void getManagedSocket_WhenPassedAValidZmqSocket_ShouldReturnARpcSocket() throws Exception {
+ //Prepare data
+ String firstAddress = "tcp://localhost:5554";
+ RpcSocket firstRpcSocket = manager.getManagedSocket(firstAddress);
+ ZMQ.Socket firstZmqSocket = firstRpcSocket.getSocket();
+
+ String secondAddress = "tcp://localhost:5555";
+ RpcSocket secondRpcSocket = manager.getManagedSocket(secondAddress);
+ ZMQ.Socket secondZmqSocket = secondRpcSocket.getSocket();
+
+ Assert.assertEquals(firstRpcSocket, manager.getManagedSocketFor(firstZmqSocket).get());
+ Assert.assertEquals(secondRpcSocket, manager.getManagedSocketFor(secondZmqSocket).get());
+ }
+
+ @Test
+ public void getManagedSocket_WhenPassedNonManagedZmqSocket_ShouldReturnNone() throws Exception {
+ ZMQ.Socket nonManagedSocket = Context.getInstance().getZmqContext().socket(ZMQ.REQ);
+ nonManagedSocket.connect("tcp://localhost:5000");
+
+ //Prepare data
+ String firstAddress = "tcp://localhost:5554";
+ RpcSocket firstRpcSocket = manager.getManagedSocket(firstAddress);
+ ZMQ.Socket firstZmqSocket = firstRpcSocket.getSocket();
+
+ Assert.assertSame(Optional.<RpcSocket>absent(), manager.getManagedSocketFor(nonManagedSocket) );
+ Assert.assertSame(Optional.<RpcSocket>absent(), manager.getManagedSocketFor(null) );
+ }
+
+ @Test
+ public void stop_WhenCalled_ShouldEmptyManagedSockets() throws Exception {
+ manager.getManagedSocket("tcp://localhost:5554");
+ manager.getManagedSocket("tcp://localhost:5555");
+ Assert.assertTrue( 2 == manager.getManagedSockets().size());
+
+ manager.close();
+ Assert.assertTrue( 0 == manager.getManagedSockets().size());
+ }
+
+ @Test
+ public void poller_WhenCalled_ShouldReturnAnInstanceOfPoller() throws Exception {
+ Assert.assertTrue (manager.getPoller() instanceof ZMQ.Poller);
+ }
+
+}
--- /dev/null
+<rpc>
+ <name>eth0</name>
+ <type>ethernetCsmacd</type>
+ <enabled>false</enabled>
+ <description>some interface</description>
+</rpc>
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>
- <artifactId>sal-test-parent</artifactId>
+ <artifactId>sal-remoterpc-connector-test-parent</artifactId>
<groupId>org.opendaylight.controller.tests</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
- <artifactId>zeromq-test-consumer</artifactId>
+ <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
<packaging>bundle</packaging>
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
<configuration>
<instructions>
<Bundle-Activator>org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer</Bundle-Activator>
- <Import-Package>
- org.opendaylight.controller.sal.core.api,
- org.opendaylight.yangtools.yang.common;version="[0.5,1)",
- org.opendaylight.yangtools.yang.data.api,
- </Import-Package>
</instructions>
</configuration>
</plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
--- /dev/null
+package org.opendaylight.controller.sample.zeromq.consumer;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Hashtable;
+import java.util.concurrent.*;
+
+import org.opendaylight.controller.sal.core.api.AbstractConsumer;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+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.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+
+import javax.xml.stream.XMLStreamException;
+
+public class ExampleConsumer extends AbstractConsumer {
+
+ private final URI namespace = URI.create("http://cisco.com/example");
+ private final QName QNAME = new QName(namespace, "heartbeat");
+
+ private ConsumerSession session;
+
+ private ServiceRegistration<ExampleConsumer> thisReg;
+ private Logger _logger = LoggerFactory.getLogger(ExampleConsumer.class);
+
+ @Override
+ public void onSessionInitiated(ConsumerSession session) {
+ this.session = session;
+ }
+
+ public RpcResult<CompositeNode> invokeRpc(QName qname, CompositeNode input) {
+ _logger.info("Invoking RPC:[{}] with Input:[{}]", qname.getLocalName(), input);
+ RpcResult<CompositeNode> result = null;
+ Future<RpcResult<CompositeNode>> future = ExampleConsumer.this.session.rpc(qname, input);
+ try {
+ result = future.get();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ _logger.info("Returning Result:[{}]", result);
+ return result;
+ }
+
+ @Override
+ protected void startImpl(BundleContext context){
+ thisReg = context.registerService(ExampleConsumer.class, this, new Hashtable<String,String>());
+ }
+ @Override
+ protected void stopImpl(BundleContext context) {
+ super.stopImpl(context);
+ thisReg.unregister();
+ }
+
+ public CompositeNode getValidCompositeNodeWithOneSimpleChild() throws FileNotFoundException {
+ InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/OneSimpleChild.xml");
+ return loadCompositeNode(xmlStream);
+ }
+
+ public CompositeNode getValidCompositeNodeWithTwoSimpleChildren() throws FileNotFoundException {
+ InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/TwoSimpleChildren.xml");
+ return loadCompositeNode(xmlStream);
+ }
+
+ public CompositeNode getValidCompositeNodeWithFourSimpleChildren() throws FileNotFoundException {
+ InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/FourSimpleChildren.xml");
+ return loadCompositeNode(xmlStream);
+ }
+
+ public CompositeNode getValidCompositeNodeWithOneSimpleOneCompositeChild() throws FileNotFoundException {
+ InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/OneSimpleOneCompositeChild.xml");
+ return loadCompositeNode(xmlStream);
+ }
+
+ public CompositeNode getValidCompositeNodeWithTwoCompositeChildren() throws FileNotFoundException {
+ InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/TwoCompositeChildren.xml");
+ return loadCompositeNode(xmlStream);
+ }
+
+ public CompositeNode getInvalidCompositeNodeSimpleChild() throws FileNotFoundException {
+ InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/InvalidSimpleChild.xml");
+ return loadCompositeNode(xmlStream);
+ }
+
+ public CompositeNode getInvalidCompositeNodeCompositeChild() throws FileNotFoundException {
+ InputStream xmlStream = ExampleConsumer.class.getResourceAsStream("/InvalidCompositeChild.xml");
+ return loadCompositeNode(xmlStream);
+ }
+
+ //Note to self: Stolen from TestUtils
+ ///Users/alefan/odl/controller4/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
+ // Figure out how to include TestUtils through pom ...was getting errors
+ private CompositeNode loadCompositeNode(InputStream xmlInputStream) throws FileNotFoundException {
+ if (xmlInputStream == null) {
+ throw new IllegalArgumentException();
+ }
+ Node<?> dataTree;
+ try {
+ dataTree = XmlTreeBuilder.buildDataTree(xmlInputStream);
+ } catch (XMLStreamException e) {
+ _logger.error("Error during building data tree from XML", e);
+ return null;
+ }
+ if (dataTree == null) {
+ _logger.error("data tree is null");
+ return null;
+ }
+ if (dataTree instanceof SimpleNode) {
+ _logger.error("RPC XML was resolved as SimpleNode");
+ return null;
+ }
+ return (CompositeNode) dataTree;
+ }
+}
--- /dev/null
+<rpc>
+ <name>eth0</name>
+ <type>ethernetCsmacd</type>
+ <enabled>false</enabled>
+ <description>some interface</description>
+</rpc>
--- /dev/null
+<rpc>
+ <innerinterface1>
+ <name>eth1</name>
+ <type>ethernet</type>
+ <enabled>false</enabled>
+ <description>some interface</description>
+ </innerinterface1>
+ <innerinterface2>
+ <name>error</name>
+ <type>ethernet</type>
+ <enabled>true</enabled>
+ <description>some interface</description>
+ </innerinterface2>
+</rpc>
--- /dev/null
+<rpc>
+ <name>error</name>
+</rpc>
--- /dev/null
+<rpc>
+ <name>eth0</name>
+</rpc>
--- /dev/null
+<rpc>
+ <name>eth0</name>
+ <innerinterface>
+ <name>eth1</name>
+ <type>ethernetCsmacd</type>
+ <enabled>false</enabled>
+ <description>some interface</description>
+ </innerinterface>
+</rpc>
--- /dev/null
+<rpc>
+ <innerinterface1>
+ <name>eth1</name>
+ <type>ethernet</type>
+ <enabled>false</enabled>
+ <description>some interface</description>
+ </innerinterface1>
+ <innerinterface2>
+ <name>eth2</name>
+ <type>ethernet</type>
+ <enabled>true</enabled>
+ <description>some interface</description>
+ </innerinterface2>
+</rpc>
--- /dev/null
+<rpc>
+ <name>eth0</name>
+ <type>ethernetCsmacd</type>
+</rpc>
\ No newline at end of file
--- /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>
+ <relativePath>../..</relativePath>
+ </parent>
+ <packaging>pom</packaging>
+ <groupId>org.opendaylight.controller.tests</groupId>
+ <artifactId>sal-remoterpc-connector-test-parent</artifactId>
+ <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>
+
+ <modules>
+ <module>consumer-service</module>
+ <module>provider-service</module>
+ <module>test-it</module>
+ <module>test-nb</module>
+ </modules>
+
+</project>
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>
- <artifactId>sal-test-parent</artifactId>
+ <artifactId>sal-remoterpc-connector-test-parent</artifactId>
<groupId>org.opendaylight.controller.tests</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
- <artifactId>zeromq-test-provider</artifactId>
+ <artifactId>sal-remoterpc-connector-test-provider</artifactId>
<packaging>bundle</packaging>
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-api</artifactId>
</dependency>
-
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-common-util</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-zeromq-connector</artifactId>
+ <artifactId>sal-remoterpc-connector</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
--- /dev/null
+package org.opendaylight.controller.sample.zeromq.provider;
+
+import org.opendaylight.controller.sal.common.util.RpcErrors;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.CompositeNodeImpl;
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+import java.util.*;
+
+public class ExampleProvider extends AbstractProvider implements RpcImplementation {
+
+ private final URI namespace = URI.create("http://cisco.com/example");
+ private final QName QNAME = new QName(namespace, "heartbeat");
+ private RpcRegistration reg;
+
+ private ServiceRegistration thisReg;
+
+ private ProviderSession session;
+ private Logger _logger = LoggerFactory.getLogger(ExampleProvider.class);
+
+ @Override
+ public void onSessionInitiated(ProviderSession session) {
+ this.session = session;
+ }
+
+ @Override
+ public Set<QName> getSupportedRpcs() {
+ Set<QName> supportedRpcs = new HashSet<QName>();
+ supportedRpcs.add(QNAME);
+ return supportedRpcs;
+ }
+
+ @Override
+ public RpcResult<CompositeNode> invokeRpc(final QName rpc, CompositeNode input) {
+ boolean success = false;
+ CompositeNode output = null;
+ Collection<RpcError> errors = new ArrayList<>();
+
+ // Only handle supported RPC calls
+ if (getSupportedRpcs().contains(rpc)) {
+ if (input == null) {
+ errors.add(RpcErrors.getRpcError("app", "tag", "info", RpcError.ErrorSeverity.WARNING, "message:null input", RpcError.ErrorType.RPC, null));
+ }
+ else {
+ if (isErroneousInput(input)) {
+ errors.add(RpcErrors.getRpcError("app", "tag", "info", RpcError.ErrorSeverity.ERROR, "message:error", RpcError.ErrorType.RPC, null));
+ }
+ else {
+ success = true;
+ output = addSuccessNode(input);
+ }
+ }
+ }
+ return Rpcs.getRpcResult(success, output, errors);
+ }
+
+ // Examines input -- dives into CompositeNodes and finds any value equal to "error"
+ private boolean isErroneousInput(CompositeNode input) {
+ for (Node<?> n : input.getChildren()) {
+ if (n instanceof CompositeNode) {
+ if (isErroneousInput((CompositeNode)n)) {
+ return true;
+ }
+ }
+ else { //SimpleNode
+ if ((input.getChildren().get(0).getValue()).equals("error")) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // Adds a child SimpleNode containing the value "success" to the input CompositeNode
+ private CompositeNode addSuccessNode(CompositeNode input) {
+ List<Node<?>> list = new ArrayList<Node<?>>(input.getChildren());
+ SimpleNodeTOImpl<String> simpleNode = new SimpleNodeTOImpl<String>(QNAME, input, "success");
+ list.add(simpleNode);
+ return new CompositeNodeTOImpl(QNAME, null, list);
+ }
+
+ @Override
+ protected void startImpl(BundleContext context) {
+ thisReg = context.registerService(ExampleProvider.class, this, new Hashtable<String, String>());
+ }
+
+ @Override
+ protected void stopImpl(BundleContext context) {
+ if (reg != null) {
+ try {
+ reg.close();
+ thisReg.unregister();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void announce(QName name) {
+ _logger.debug("Announcing [{}]\n\n\n", name);
+ reg = this.session.addRpcImplementation(name, this);
+ }
+
+}
--- /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>
+ <artifactId>sal-remoterpc-connector-test-parent</artifactId>
+ <groupId>org.opendaylight.controller.tests</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-remoterpc-connector-test-it</artifactId>
+ <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>
+
+ <properties>
+ <exam.version>3.0.0</exam.version>
+ <url.version>1.5.0</url.version>
+ <config.version>0.2.3-SNAPSHOT</config.version>
+ <netconf.version>0.2.3-SNAPSHOT</netconf.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.7</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>maven-paxexam-plugin</artifactId>
+ <version>1.2.4</version>
+ <executions>
+ <execution>
+ <id>generate-config</id>
+ <goals>
+ <goal>generate-depends-file</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse
+ m2e settings only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ org.ops4j.pax.exam
+ </groupId>
+ <artifactId>
+ maven-paxexam-plugin
+ </artifactId>
+ <versionRange>
+ [1.2.4,)
+ </versionRange>
+ <goals>
+ <goal>
+ generate-depends-file
+ </goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+ <artifactId>xtend-lib-osgi</artifactId>
+ <version>2.4.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.tests</groupId>
+ <artifactId>sal-remoterpc-connector-test-provider</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.tests</groupId>
+ <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-container-native</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-junit4</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-link-mvn</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.url</groupId>
+ <artifactId>pax-url-aether</artifactId>
+ <version>1.5.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <version>3.8.1.v20120830-144521</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-remoterpc-connector</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </exclusion>
+ <exclusion>
+ <artifactId>commons-io</artifactId>
+ <groupId>commons-io</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-api</artifactId>
+ </dependency>
+ <!--dependency> <groupId>org.opendaylight.yangtools</groupId> <artifactId>yang-data-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version> </dependency -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-parser-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+ <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+ <version>4.0</version>
+ </dependency>
+
+ <!-- routing table dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>zeromq-routingtable.implementation</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.implementation</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>commons-io</artifactId>
+ <groupId>commons-io</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </exclusion>
+ <exclusion>
+ <artifactId>commons-io</artifactId>
+ <groupId>commons-io</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager.it.implementation</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>commons-io</artifactId>
+ <groupId>commons-io</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.stub</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>commons-io</artifactId>
+ <groupId>commons-io</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
+ <version>3.0.1</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>eclipselink</groupId>
+ <artifactId>javax.resource</artifactId>
+ <version>1.5.0.v200906010428</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>ietf-netconf-monitoring</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ <version>2013.09.07.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>opendaylight-l2-types</artifactId>
+ <version>2013.08.27.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-it</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-connector-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <version>3.8.1.v20120830-144521</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ <version>1.9.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-core-asl</artifactId>
+ <version>1.9.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.zeromq</groupId>
+ <artifactId>jeromq</artifactId>
+ <version>0.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+ <artifactId>xtend-lib-osgi</artifactId>
+ <version>2.4.3</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-container-native</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-junit4</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-netconf-connector</artifactId>
+ <version>${netconf.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-store-impl</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>logback-config</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-impl</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-file-adapter</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-impl</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-client</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam</artifactId>
+ <version>${exam.version}</version>
+ <!-- Compile scope here is intentional, it is used in TestHelper
+ class which could be downloaded via nexus and reused in other integration
+ tests. -->
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-link-mvn</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <version>3.8.1.v20120830-144521</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>commons-io</artifactId>
+ <groupId>commons-io</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-management</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+ <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+ <version>4.0</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * 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.sample.zeromq.test.it;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.sal.connector.remoterpc.Client;
+import org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcClient;
+import org.opendaylight.controller.sal.connector.remoterpc.RemoteRpcServer;
+import org.opendaylight.controller.sal.connector.remoterpc.ServerImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sample.zeromq.provider.ExampleProvider;
+import org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer;
+import org.opendaylight.controller.test.sal.binding.it.TestHelper;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.util.Filter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import javax.inject.Inject;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Hashtable;
+
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.baseModelBundles;
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.bindingAwareSalBundles;
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.configMinumumBundles;
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.mdSalCoreBundles;
+import static org.ops4j.pax.exam.CoreOptions.*;
+
+@RunWith(PaxExam.class)
+public class RouterTest {
+
+ private Logger _logger = LoggerFactory.getLogger(RouterTest.class);
+
+ public static final String ODL = "org.opendaylight.controller";
+ public static final String YANG = "org.opendaylight.yangtools";
+ public static final String SAMPLE = "org.opendaylight.controller.tests";
+ private final URI namespace = URI.create("http://cisco.com/example");
+ private final QName QNAME = new QName(namespace, "heartbeat");
+
+
+ @Inject
+ org.osgi.framework.BundleContext ctx;
+
+ @Inject
+ @Filter(timeout=60*1000)
+ Broker broker;
+
+ private ZMQ.Context zmqCtx = ZMQ.context(1);
+ //private Server router;
+ //private ExampleProvider provider;
+
+ //@Test
+ public void testInvokeRpc() throws Exception{
+ //Thread.sleep(1000);
+ //Send announcement
+ ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+ Assert.assertNotNull(providerRef);
+
+ ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+ Assert.assertNotNull(provider);
+
+ ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+ Assert.assertNotNull(consumerRef);
+ ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+ Assert.assertNotNull(consumer);
+
+
+ _logger.debug("Provider sends announcement [{}]", "heartbeat");
+ provider.announce(QNAME);
+ ServiceReference routerRef = ctx.getServiceReference(Client.class);
+ Client router = (Client) ctx.getService(routerRef);
+ _logger.debug("Found router[{}]", router);
+ _logger.debug("Invoking RPC [{}]", QNAME);
+ for (int i = 0; i < 3; i++) {
+ RpcResult<CompositeNode> result = router.invokeRpc(QNAME, consumer.getValidCompositeNodeWithOneSimpleChild());
+ _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+ Assert.assertNotNull(result);
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithValidSimpleNode() throws Exception{
+ //Thread.sleep(1500);
+
+ ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+ Assert.assertNotNull(providerRef);
+ ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+ Assert.assertNotNull(provider);
+ ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+ Assert.assertNotNull(consumerRef);
+ ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+ Assert.assertNotNull(consumer);
+
+ // Provider sends announcement
+ _logger.debug("Provider sends announcement [{}]", "heartbeat");
+ provider.announce(QNAME);
+ // Consumer invokes RPC
+ _logger.debug("Invoking RPC [{}]", QNAME);
+ CompositeNode input = consumer.getValidCompositeNodeWithOneSimpleChild();
+ for (int i = 0; i < 3; i++) {
+ RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+ Assert.assertNotNull(result);
+ _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+ Assert.assertTrue(result.isSuccessful());
+ Assert.assertNotNull(result.getResult());
+ Assert.assertEquals(0, result.getErrors().size());
+ Assert.assertEquals(input.getChildren().size()+1, result.getResult().getChildren().size());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithValidSimpleNodes() throws Exception{
+ //Thread.sleep(1500);
+
+ ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+ Assert.assertNotNull(providerRef);
+ ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+ Assert.assertNotNull(provider);
+ ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+ Assert.assertNotNull(consumerRef);
+ ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+ Assert.assertNotNull(consumer);
+
+ // Provider sends announcement
+ _logger.debug("Provider sends announcement [{}]", "heartbeat");
+ provider.announce(QNAME);
+ // Consumer invokes RPC
+ _logger.debug("Invoking RPC [{}]", QNAME);
+ CompositeNode input = consumer.getValidCompositeNodeWithFourSimpleChildren();
+ for (int i = 0; i < 3; i++) {
+ RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+ Assert.assertNotNull(result);
+ _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+ Assert.assertTrue(result.isSuccessful());
+ Assert.assertNotNull(result.getResult());
+ Assert.assertEquals(0, result.getErrors().size());
+ Assert.assertEquals(input.getChildren().size()+1, result.getResult().getChildren().size());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithValidCompositeNode() throws Exception{
+ //Thread.sleep(1500);
+
+ ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+ Assert.assertNotNull(providerRef);
+ ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+ Assert.assertNotNull(provider);
+ ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+ Assert.assertNotNull(consumerRef);
+ ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+ Assert.assertNotNull(consumer);
+
+ // Provider sends announcement
+ _logger.debug("Provider sends announcement [{}]", "heartbeat");
+ provider.announce(QNAME);
+ // Consumer invokes RPC
+ _logger.debug("Invoking RPC [{}]", QNAME);
+ CompositeNode input = consumer.getValidCompositeNodeWithTwoCompositeChildren();
+ for (int i = 0; i < 3; i++) {
+ RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+ Assert.assertNotNull(result);
+ _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+ Assert.assertTrue(result.isSuccessful());
+ Assert.assertNotNull(result.getResult());
+ Assert.assertEquals(0, result.getErrors().size());
+ Assert.assertEquals(input.getChildren().size()+1, result.getResult().getChildren().size());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNullInput() throws Exception{
+ //Thread.sleep(1500);
+
+ ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+ Assert.assertNotNull(providerRef);
+ ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+ Assert.assertNotNull(provider);
+ ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+ Assert.assertNotNull(consumerRef);
+ ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+ Assert.assertNotNull(consumer);
+
+ // Provider sends announcement
+ _logger.debug("Provider sends announcement [{}]", QNAME.getLocalName());
+ provider.announce(QNAME);
+ // Consumer invokes RPC
+ _logger.debug("Invoking RPC [{}]", QNAME);
+ for (int i = 0; i < 3; i++) {
+ RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, null);
+ Assert.assertNotNull(result);
+ _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+ Assert.assertFalse(result.isSuccessful());
+ Assert.assertNull(result.getResult());
+ Assert.assertEquals(1, result.getErrors().size());
+ Assert.assertEquals(RpcError.ErrorSeverity.WARNING, ((RpcError)result.getErrors().toArray()[0]).getSeverity());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithInvalidSimpleNode() throws Exception{
+ //Thread.sleep(1500);
+
+ ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+ Assert.assertNotNull(providerRef);
+ ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+ Assert.assertNotNull(provider);
+ ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+ Assert.assertNotNull(consumerRef);
+ ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+ Assert.assertNotNull(consumer);
+
+ // Provider sends announcement
+ _logger.debug("Provider sends announcement [{}]", QNAME.getLocalName());
+ provider.announce(QNAME);
+ // Consumer invokes RPC
+ _logger.debug("Invoking RPC [{}]", QNAME);
+ CompositeNode input = consumer.getInvalidCompositeNodeSimpleChild();
+ for (int i = 0; i < 3; i++) {
+ RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+ Assert.assertNotNull(result);
+ _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+ Assert.assertFalse(result.isSuccessful());
+ Assert.assertNull(result.getResult());
+ Assert.assertEquals(1, result.getErrors().size());
+ Assert.assertEquals(RpcError.ErrorSeverity.ERROR, ((RpcError)result.getErrors().toArray()[0]).getSeverity());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithInvalidCompositeNode() throws Exception{
+ //Thread.sleep(1500);
+
+ ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+ Assert.assertNotNull(providerRef);
+ ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+ Assert.assertNotNull(provider);
+ ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+ Assert.assertNotNull(consumerRef);
+ ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+ Assert.assertNotNull(consumer);
+
+ // Provider sends announcement
+ _logger.debug("Provider sends announcement [{}]", QNAME.getLocalName());
+ provider.announce(QNAME);
+ // Consumer invokes RPC
+ _logger.debug("Invoking RPC [{}]", QNAME);
+ CompositeNode input = consumer.getInvalidCompositeNodeCompositeChild();
+ for (int i = 0; i < 3; i++) {
+ RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, input);
+ Assert.assertNotNull(result);
+ _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+ Assert.assertFalse(result.isSuccessful());
+ Assert.assertNull(result.getResult());
+ Assert.assertEquals(1, result.getErrors().size());
+ Assert.assertEquals(RpcError.ErrorSeverity.ERROR, ((RpcError)result.getErrors().toArray()[0]).getSeverity());
+ }
+ }
+
+ //@Test
+ // This method is UNTESTED -- need to get around the bundling issues before I know if this even work
+// public void testInvokeRpcWithValidCompositeNode() throws Exception{
+// Thread.sleep(10000);
+// //Send announcement
+// ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+// Assert.assertNotNull(providerRef);
+//
+// ExampleProvider provider = (ExampleProvider)ctx.getService(providerRef);
+// Assert.assertNotNull(provider);
+//
+// ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+// Assert.assertNotNull(consumerRef);
+//
+// ExampleConsumer consumer = (ExampleConsumer)ctx.getService(consumerRef);
+// Assert.assertNotNull(consumer);
+//
+// _logger.debug("Provider sends announcement [{}]", "heartbeat");
+// provider.announce(QNAME);
+// ServiceReference routerRef = ctx.getServiceReference(Client.class);
+// Client router = (Client) ctx.getService(routerRef);
+// _logger.debug("Found router[{}]", router);
+// _logger.debug("Invoking RPC [{}]", QNAME);
+// for (int i = 0; i < 3; i++) {
+// RpcResult<CompositeNode> result = router.getInstance().invokeRpc(QNAME, consumer.getValidCompositeNodeWithOneSimpleChild());
+// _logger.debug("{}-> Result is: Successful:[{}], Payload:[{}], Errors: [{}]", i, result.isSuccessful(), result.getResult(), result.getErrors());
+// Assert.assertNotNull(result);
+// }
+// }
+
+ private Message send(Message msg) throws IOException {
+ ZMQ.Socket reqSocket = zmqCtx.socket(ZMQ.REQ);
+ reqSocket.connect("tcp://localhost:5555");
+ reqSocket.send(Message.serialize(msg));
+ Message response = parseMessage(reqSocket);
+
+ return response;
+ }
+
+ /**
+ * @param socket
+ * @return
+ */
+ private Message parseMessage(ZMQ.Socket socket) {
+
+ Message msg = null;
+ try {
+ byte[] bytes = socket.recv();
+ _logger.debug("Received bytes:[{}]", bytes.length);
+ msg = (Message) Message.deserialize(bytes);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ return msg;
+ }
+
+
+ private void printState(){
+ Bundle[] b = ctx.getBundles();
+ _logger.debug("\n\nNumber of bundles [{}]\n\n]", b.length);
+ for (int i=0;i<b.length;i++){
+ _logger.debug("Bundle States {}-{} ",b[i].getSymbolicName(), stateToString(b[i].getState()));
+
+ if ( Bundle.INSTALLED == b[i].getState() || (Bundle.RESOLVED == b[i].getState())){
+ try {
+ b[i].start();
+ } catch (BundleException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ private String stateToString(int state) {
+ switch (state) {
+ case Bundle.ACTIVE:
+ return "ACTIVE";
+ case Bundle.INSTALLED:
+ return "INSTALLED";
+ case Bundle.RESOLVED:
+ return "RESOLVED";
+ case Bundle.UNINSTALLED:
+ return "UNINSTALLED";
+ default:
+ return "Not CONVERTED";
+ }
+ }
+
+ @Configuration
+ public Option[] config() {
+ return options(systemProperty("osgi.console").value("2401"),
+ systemProperty("rpc.port").value("5555"),
+ mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
+ mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
+ mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
+ mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
+
+ //mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject().update(), //
+ mavenBundle(ODL, "sal-common").versionAsInProject(), //
+ mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
+ mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
+ mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
+ mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
+ mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
+ mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
+ mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
+
+
+
+ baseModelBundles(),
+ bindingAwareSalBundles(),
+ TestHelper.bindingIndependentSalBundles(),
+ TestHelper.configMinumumBundles(),
+ TestHelper.mdSalCoreBundles(),
+
+ //Added the consumer
+ mavenBundle(SAMPLE, "sal-remoterpc-connector-test-consumer").versionAsInProject(), //
+ //**** These two bundles below are NOT successfully resolved -- some of their dependencies must be missing
+ //**** This causes the "Message" error to occur, the class cannot be found
+ mavenBundle(SAMPLE, "sal-remoterpc-connector-test-provider").versionAsInProject(), //
+ mavenBundle(ODL, "sal-remoterpc-connector").versionAsInProject(), //
+
+ mavenBundle(ODL, "zeromq-routingtable.implementation").versionAsInProject(),
+ mavenBundle(YANG, "concepts").versionAsInProject(),
+ mavenBundle(YANG, "yang-binding").versionAsInProject(), //
+ mavenBundle(YANG, "yang-common").versionAsInProject(), //
+ mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
+ mavenBundle(YANG, "yang-data-impl").versionAsInProject(), //
+ mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
+ mavenBundle(YANG, "yang-parser-api").versionAsInProject(), //
+ mavenBundle(YANG, "yang-parser-impl").versionAsInProject(), //
+ mavenBundle(YANG, "yang-model-util").versionAsInProject(), //
+ mavenBundle(YANG + ".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
+ mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
+ mavenBundle("com.google.guava", "guava").versionAsInProject(), //
+ mavenBundle("org.zeromq", "jeromq").versionAsInProject(),
+ mavenBundle("org.codehaus.jackson", "jackson-mapper-asl").versionAsInProject(),
+ mavenBundle("org.codehaus.jackson", "jackson-core-asl").versionAsInProject(),
+ //routingtable dependencies
+ systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
+ // List framework bundles
+ mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.eclipse.osgi.services").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell").versionAsInProject(),
+ // List logger bundles
+
+ mavenBundle("org.opendaylight.controller", "clustering.services")
+ .versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "clustering.stub")
+ .versionAsInProject(),
+
+
+ // List all the bundles on which the test case depends
+ mavenBundle("org.opendaylight.controller", "sal")
+ .versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "sal.implementation")
+ .versionAsInProject(),
+ mavenBundle("org.jboss.spec.javax.transaction",
+ "jboss-transaction-api_1.1_spec").versionAsInProject(),
+ mavenBundle("org.apache.commons", "commons-lang3")
+ .versionAsInProject(),
+ mavenBundle("org.apache.felix",
+ "org.apache.felix.dependencymanager")
+ .versionAsInProject(),
+
+ junitBundles()
+ );
+ }
+
+}
--- /dev/null
+//START OF CONFIG-LAST
+<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
+ <name>yang-schema-service</name>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:hash-map-data-store</type>
+ <name>hash-map-data-store</name>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
+ <name>dom-broker</name>
+ <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
+ <name>ref_hash-map-data-store</name>
+ </data-store>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
+ <name>binding-broker-impl</name>
+ <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+ <name>ref_binding-notification-broker</name>
+ </notification-service>
+ <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <name>ref_binding-data-broker</name>
+ </data-broker>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
+ <name>runtime-mapping-singleton</name>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
+ <name>binding-notification-broker</name>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-broker</type>
+ <name>binding-data-broker</name>
+ <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <name>ref_dom-broker</name>
+ </dom-broker>
+ <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+ <name>ref_runtime-mapping-singleton</name>
+ </mapping-service>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">prefix:remote-zeromq-rpc-server</type>
+ <name>remoter</name>
+ <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">5666</port>
+ <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
+ <name>ref_dom-broker</name>
+ </dom-broker>
+ </module>
+</modules>
+<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <instance>
+ <name>ref_yang-schema-service</name>
+ <provider>/config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+ <instance>
+ <name>ref_binding-notification-broker</name>
+ <provider>/config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
+ <instance>
+ <name>ref_hash-map-data-store</name>
+ <provider>/config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <instance>
+ <name>ref_binding-broker-impl</name>
+ <provider>/config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
+ <instance>
+ <name>ref_runtime-mapping-singleton</name>
+ <provider>/config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <instance>
+ <name>ref_dom-broker</name>
+ <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <instance>
+ <name>ref_binding-data-broker</name>
+ <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
+ </instance>
+ </service>
+</services>
+</data>
+
+
+//END OF SNAPSHOT
+urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28
+urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc?module=odl-sal-dom-rpc-remote-cfg&revision=2013-10-28
+//END OF CONFIG
--- /dev/null
+<configuration scan="true">
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+ </pattern>
+ </encoder>
+ </appender>
+
+
+ <logger name="org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort" level="ERROR"/>
+
+ <root level="info">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+ <artifactId>sal-remoterpc-connector-test-parent</artifactId>
+ <groupId>org.opendaylight.controller.tests</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>sal-remoterpc-connector-test-nb</artifactId>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${bundle.plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ </Export-Package>
+ <Import-Package>
+ com.sun.jersey.spi.container.servlet,
+ org.codehaus.jackson.annotate,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ javax.xml.bind,
+ javax.xml.bind.annotation,
+ org.slf4j,
+ org.apache.catalina.filters,
+ org.codehaus.jackson.jaxrs,
+ org.opendaylight.controller.sample.zeromq.provider,
+ org.opendaylight.controller.sample.zeromq.consumer,
+ org.opendaylight.controller.sal.utils,
+ org.opendaylight.yangtools.yang.common,
+ org.opendaylight.controller.sal.connector.api,
+ org.opendaylight.controller.sal.connector.remoterpc.api;version="[0.4,1)",
+ org.opendaylight.controller.sal.connector.remoterpc.impl;version="[0.4,1)",
+ org.opendaylight.controller.sal.connector.remoterpc.dto,
+ org.opendaylight.controller.sal.connector.remoterpc.util,
+ org.osgi.framework,
+ com.google.common.base,
+ org.opendaylight.yangtools.yang.data.api,
+ !org.codehaus.enunciate.jaxrs
+
+ </Import-Package>
+ <Web-ContextPath>/controller/nb/v2/zmqnb</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
+ </instructions>
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.tests</groupId>
+ <artifactId>sal-remoterpc-connector-test-provider</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.tests</groupId>
+ <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-remoterpc-connector</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>5.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>zeromq-routingtable.implementation</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ </dependencies>
+
+ </project>
--- /dev/null
+package org.opendaylight.controller.tests.zmqrouter.rest;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
+import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
+import org.opendaylight.controller.sal.connector.remoterpc.dto.CompositeNodeImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.impl.RoutingTableImpl;
+import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
+import org.opendaylight.controller.sample.zeromq.consumer.ExampleConsumer;
+import org.opendaylight.controller.sample.zeromq.provider.ExampleProvider;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.io.Serializable;
+import java.net.URI;
+import java.util.Set;
+
+@Path("router")
+public class Router {
+ private Logger _logger = LoggerFactory.getLogger(Router.class);
+ private final URI namespace = URI.create("http://cisco.com/example");
+ private final QName QNAME = new QName(namespace, "heartbeat");
+
+
+ @GET
+ @Path("/hello")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String hello() {
+ return "Hello";
+ }
+
+ @GET
+ @Path("/announce")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String announce() {
+ _logger.info("Announce request received");
+
+ BundleContext ctx = getBundleContext();
+ ServiceReference providerRef = ctx.getServiceReference(ExampleProvider.class);
+ if (providerRef == null) {
+ _logger.debug("Could not get provider reference");
+ return "Could not get provider reference";
+ }
+
+ ExampleProvider provider = (ExampleProvider) ctx.getService(providerRef);
+ if (provider == null) {
+ _logger.info("Could not get provider service");
+ return "Could not get provider service";
+ }
+
+ provider.announce(QNAME);
+ return "Announcement sent ";
+
+ }
+
+ @GET
+ @Path("/rpc")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String invokeRpc() throws Exception {
+ _logger.info("Invoking RPC");
+
+ ExampleConsumer consumer = getConsumer();
+ RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, new CompositeNodeImpl());
+ _logger.info("Result [{}]", result.isSuccessful());
+
+ return stringify(result);
+ }
+
+ @GET
+ @Path("/rpc-success")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String invokeRpcSuccess() throws Exception {
+ ExampleConsumer consumer = getConsumer();
+ RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, consumer.getValidCompositeNodeWithFourSimpleChildren()); //TODO: Change this
+ _logger.info("Result [{}]", result.isSuccessful());
+
+ return stringify(result);
+ }
+
+ @GET
+ @Path("/rpc-failure")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String invokeRpcFailure() throws Exception {
+ ExampleConsumer consumer = getConsumer();
+ //RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, consumer.getInvalidCompositeNodeCompositeChild()); //TODO: Change this
+ RpcResult<CompositeNode> result = consumer.invokeRpc(QNAME, null); //TODO: Change this
+ _logger.info("Result [{}]", result.isSuccessful());
+
+ return stringify(result);
+ }
+
+ @GET
+ @Path("/routingtable")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String invokeRoutingTable() {
+ _logger.info("Invoking adding an entry in routing table");
+
+ BundleContext ctx = getBundleContext();
+ ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
+ if (routingTableServiceReference == null) {
+ _logger.debug("Could not get routing table impl reference");
+ return "Could not get routingtable referen ";
+ }
+ RoutingTable routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
+ if (routingTable == null) {
+ _logger.info("Could not get routing table service");
+ return "Could not get routing table service";
+ }
+
+
+ RoutingIdentifierImpl rii = new RoutingIdentifierImpl();
+ try {
+ routingTable.addGlobalRoute(rii.toString(), "172.27.12.1:5000");
+ } catch (RoutingTableException e) {
+ _logger.error("error in adding routing identifier" + e.getMessage());
+
+ } catch (SystemException e) {
+ _logger.error("error in adding routing identifier" + e.getMessage());
+ }
+
+ Set<String> routes = routingTable.getRoutes(rii.toString());
+
+ StringBuilder stringBuilder = new StringBuilder();
+ for (String route : routes) {
+ stringBuilder.append(route);
+ }
+
+ _logger.info("Result [{}] routes added for route" + rii + stringBuilder.toString());
+
+ return stringBuilder.toString();
+ }
+
+ @GET
+ @Path("/routingtabledelete")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String invokeDeleteRoutingTable() {
+ _logger.info("Invoking adding an entry in routing table");
+
+ BundleContext ctx = getBundleContext();
+ ServiceReference routingTableServiceReference = ctx.getServiceReference(RoutingTable.class);
+ if (routingTableServiceReference == null) {
+ _logger.debug("Could not get routing table impl reference");
+ return "Could not get routingtable referen ";
+ }
+ RoutingTable routingTable = (RoutingTableImpl) ctx.getService(routingTableServiceReference);
+ if (routingTable == null) {
+ _logger.info("Could not get routing table service");
+ return "Could not get routing table service";
+ }
+
+
+ RoutingIdentifierImpl rii = new RoutingIdentifierImpl();
+ try {
+ routingTable.removeGlobalRoute(rii.toString());
+ } catch (RoutingTableException e) {
+ _logger.error("error in adding routing identifier" + e.getMessage());
+
+ } catch (SystemException e) {
+ _logger.error("error in adding routing identifier" + e.getMessage());
+ }
+
+ Set<String> routes = routingTable.getRoutes(rii.toString());
+
+ StringBuilder stringBuilder = new StringBuilder();
+ if (routes != null) {
+ for (String route : routes) {
+ stringBuilder.append(route);
+ }
+ } else {
+ stringBuilder.append(" successfully");
+ }
+
+ _logger.info("Result [{}] routes removed for route" + rii + stringBuilder.toString());
+
+ return stringBuilder.toString();
+ }
+
+ private String stringify(RpcResult<CompositeNode> result) {
+ CompositeNode node = result.getResult();
+ StringBuilder builder = new StringBuilder("result:").append(XmlUtils.compositeNodeToXml(node)).append("\n")
+ .append("error:").append(result.getErrors()).append("\n");
+
+ return builder.toString();
+ }
+
+ private BundleContext getBundleContext() {
+ ClassLoader tlcl = Thread.currentThread().getContextClassLoader();
+ Bundle bundle = null;
+
+ if (tlcl instanceof BundleReference) {
+ bundle = ((BundleReference) tlcl).getBundle();
+ } else {
+ _logger.info("Unable to determine the bundle context based on " +
+ "thread context classloader.");
+ bundle = FrameworkUtil.getBundle(this.getClass());
+ }
+ return (bundle == null ? null : bundle.getBundleContext());
+ }
+
+ private ExampleConsumer getConsumer() {
+ BundleContext ctx = getBundleContext();
+ ServiceReference consumerRef = ctx.getServiceReference(ExampleConsumer.class);
+ if (consumerRef == null) {
+ _logger.debug("Could not get consumer reference");
+ throw new NullPointerException("Could not get consumer reference");
+ }
+ ExampleConsumer consumer = (ExampleConsumer) ctx.getService(consumerRef);
+ if (consumer == null) {
+ _logger.info("Could not get consumer service");
+ throw new NullPointerException("Could not get consumer service");
+ }
+ return consumer;
+ }
+
+ class RoutingIdentifierImpl implements RpcRouter.RouteIdentifier, Serializable {
+
+ private final URI namespace = URI.create("http://cisco.com/example");
+ private final QName QNAME = new QName(namespace, "global");
+ private final QName instance = new QName(URI.create("127.0.0.1"), "local");
+
+ @Override
+ public QName getContext() {
+ return QNAME;
+ }
+
+ @Override
+ public QName getType() {
+ return QNAME;
+ }
+
+ @Override
+ public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier getRoute() {
+ return InstanceIdentifier.of(instance);
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <servlet>
+ <servlet-name>JAXRSZmq</servlet-name>
+ <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>JAXRSZmq</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>NB api</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ <http-method>POST</http-method>
+ <http-method>GET</http-method>
+ <http-method>PUT</http-method>
+ <http-method>PATCH</http-method>
+ <http-method>DELETE</http-method>
+ <http-method>HEAD</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>System-Admin</role-name>
+ <role-name>Network-Admin</role-name>
+ <role-name>Network-Operator</role-name>
+ <role-name>Container-User</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <security-role>
+ <role-name>System-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Operator</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Container-User</role-name>
+ </security-role>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>opendaylight</realm-name>
+ </login-config>
+</web-app>
import org.opendaylight.controller.sal.rest.api.Draft01;
import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
throws IOException, WebApplicationException {
CompositeNode data = t.getData();
if (data == null) {
- throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build());
+ throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
}
JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, "UTF-8"));
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
import org.opendaylight.yangtools.yang.common.QName
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import static javax.ws.rs.core.Response.Status.*
class RestconfImpl implements RestconfService {
-
+
val static RestconfImpl INSTANCE = new RestconfImpl
@Property
@Property
extension ControllerContext controllerContext
-
+
private new() {
if (INSTANCE !== null) {
throw new IllegalStateException("Already instantiated");
}
}
-
+
static def getInstance() {
return INSTANCE
}
override createConfigurationData(String identifier, CompositeNode payload) {
val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
- val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
+ val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get();
switch status.result {
- case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build
- default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
+ case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
+ default: Response.status(INTERNAL_SERVER_ERROR).build
}
}
override updateConfigurationData(String identifier, CompositeNode payload) {
val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
- val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
+ val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get();
switch status.result {
- case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build
- default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
+ case TransactionStatus.COMMITED: Response.status(OK).build
+ default: Response.status(INTERNAL_SERVER_ERROR).build
}
}
override invokeRpc(String identifier, CompositeNode payload) {
val rpc = identifier.rpcDefinition
if (rpc === null) {
- throw new ResponseException(Response.Status.NOT_FOUND, "RPC does not exist.");
+ throw new ResponseException(NOT_FOUND, "RPC does not exist.");
}
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)
val rpcResult = broker.invokeRpc(rpc.QName, rpcRequest);
- return new StructuredData(rpcResult.result, rpc.output);
+ if (!rpcResult.successful) {
+ throw new ResponseException(INTERNAL_SERVER_ERROR, "Operation failed")
+ }
+ if (rpcResult.result === null) {
+ return null
+ }
+ return new StructuredData(rpcResult.result, rpc.output)
}
-
+
override readConfigurationData(String identifier) {
val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
val data = broker.readConfigurationData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
}
-
+
override readOperationalData(String identifier) {
val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
}
-
+
override updateConfigurationDataLegacy(String identifier, CompositeNode payload) {
- updateConfigurationData(identifier,payload);
+ updateConfigurationData(identifier, payload);
}
-
+
override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
- createConfigurationData(identifier,payload);
+ createConfigurationData(identifier, payload);
}
-
+
private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) {
val identifierWithSchemaNode = identifier.toInstanceIdentifier
if (identifierWithSchemaNode === null) {
- throw new ResponseException(Response.Status.BAD_REQUEST, "URI has bad format");
+ throw new ResponseException(BAD_REQUEST, "URI has bad format");
}
return identifierWithSchemaNode
}
-
+
private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) {
if (node instanceof CompositeNodeWrapper) {
- normalizeNode(node as CompositeNodeWrapper, schema,null)
+ normalizeNode(node as CompositeNodeWrapper, schema, null)
return (node as CompositeNodeWrapper).unwrap()
}
return node
}
- private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema,QName previousAugment) {
+ private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment) {
if (schema === null) {
- throw new ResponseException(Response.Status.BAD_REQUEST,
+ throw new ResponseException(BAD_REQUEST,
"Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
}
var validQName = schema.QName
var currentAugment = previousAugment;
- if(schema.augmenting) {
+ if (schema.augmenting) {
currentAugment = schema.QName
- } else if(previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
- validQName = QName.create(currentAugment,schema.QName.localName);
+ } 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 = validQName
} else {
- throw new ResponseException(Response.Status.BAD_REQUEST,
+ throw new ResponseException(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) {
normalizeNode(child,
- findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),currentAugment)
+ 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) {
+ if (schema instanceof LeafSchemaNode) {
emptyNodeBuilder.setComposite(false);
- } else if(schema instanceof ContainerSchemaNode) {
+ } 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) {
for (caze : (schema as ChoiceNode).cases) {
- val result = findFirstSchemaByLocalName(localName, caze.childNodes)
+ val result = findFirstSchemaByLocalName(localName, caze.childNodes)
if (result !== null) {
return result
}
}
} else {
val result = schemas.findFirst[n|n.QName.localName.equals(localName)]
- if(result !== null) {
+ if (result !== null) {
return result;
-
+
}
}
}
@Override
public RpcResult<CompositeNode> answer(InvocationOnMock invocation) throws Throwable {
CompositeNode compNode = (CompositeNode) invocation.getArguments()[1];
- return new DummyRpcResult.Builder<CompositeNode>().result(compNode).build();
+ return new DummyRpcResult.Builder<CompositeNode>().result(compNode).isSuccessful(true).build();
}
}
String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
Response response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
- assertEquals(204, response.getStatus());
- response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
assertEquals(200, response.getStatus());
+ response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
+ assertEquals(204, response.getStatus());
uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
response = target(uri).request(MEDIA_TYPE_DRAFT02).put(entity);
- assertEquals(204, response.getStatus());
- response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
assertEquals(200, response.getStatus());
+ response = target(uri).request(MEDIA_TYPE_DRAFT02).post(entity);
+ assertEquals(204, response.getStatus());
uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0");
response = target(uri).request(MEDIA_TYPE).put(entity);
- assertEquals(204, response.getStatus());
- response = target(uri).request(MEDIA_TYPE).post(entity);
assertEquals(200, response.getStatus());
+ response = target(uri).request(MEDIA_TYPE).post(entity);
+ assertEquals(204, response.getStatus());
}
@Test
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<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-zeromq-connector</artifactId>
- <packaging>bundle</packaging>
-
- <properties>
- <scala.version>2.10.3</scala.version>
- </properties>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Import-Package>
- org.opendaylight.controller.sal.connector.api,
- org.opendaylight.controller.sal.core.api,
- org.opendaylight.yangtools.concepts;version="[0.1,1)",
- org.opendaylight.yangtools.yang.common;version="[0.5,1)",
- org.opendaylight.yangtools.yang.data.api;version="[0.5,1)",
- org.zeromq;version="[0.3,1)"
- </Import-Package>
- <Bundle-Activator>org.opendaylight.controller.sal.connector.remoterpc.router.zeromq.Activator</Bundle-Activator>
- </instructions>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>net.alchim31.maven</groupId>
- <artifactId>scala-maven-plugin</artifactId>
- <version>3.1.6</version>
- <configuration>
- <recompileMode>incremental</recompileMode>
- <args>
- <arg>-target:jvm-1.7</arg>
- </args>
- <javacArgs>
- <javacArg>-source</javacArg><javacArg>1.7</javacArg>
- <javacArg>-target</javacArg><javacArg>1.7</javacArg>
- </javacArgs>
- </configuration>
- <executions>
- <execution>
- <id>scala-compile</id>
- <goals>
- <goal>compile</goal>
- </goals>
- </execution>
- <execution>
- <id>scala-test-compile</id>
- <goals>
- <goal>testCompile</goal>
- </goals>
- </execution>
- </executions>
-
- </plugin>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <executions>
- <execution>
- <id>default-compile</id>
- <phase>none</phase>
- </execution>
- <execution>
- <id>default-testCompile</id>
- <phase>none</phase>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-
- <dependencies>
- <dependency>
- <groupId>org.scala-lang</groupId>
- <artifactId>scala-library</artifactId>
- <version>${scala.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>containermanager</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.northbound</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-connector-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
-
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
- <dependency>
- <groupId>org.jeromq</groupId>
- <artifactId>jeromq</artifactId>
- <version>0.3.0-SNAPSHOT</version>
- </dependency>
-
- </dependencies>
- <repositories>
- <repository>
- <id>sonatype-nexus-snapshots</id>
- <url>https://oss.sonatype.org/content/repositories/snapshots</url>
- <releases>
- <enabled>false</enabled>
- </releases>
- <snapshots>
- <enabled>true</enabled>
- </snapshots>
- </repository>
- </repositories>
-
-</project>
+++ /dev/null
-/*
- * 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.connector.remoterpc.api;
-
-import java.util.Map;
-import java.util.Set;
-
-public interface RouteChange<I, R> {
-
- Map<I, Set<R>> getRemovals();
- Map<I, Set<R>> getAnnouncements();
-}
+++ /dev/null
-/*
- * 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.connector.remoterpc.router.zeromq;
-
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.osgi.framework.BundleContext;
-
-public class Activator extends AbstractProvider {
-
- ZeroMqRpcRouter router;
-
- @Override
- public void onSessionInitiated(ProviderSession session) {
- router = ZeroMqRpcRouter.getInstance();
- router.setBrokerSession(session);
- router.start();
- }
-
- @Override
- protected void stopImpl(BundleContext context) {
- router.stop();
- }
-
-}
+++ /dev/null
-/*
- * 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.connector.remoterpc.router.zeromq;
-
-import java.io.IOException;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.connector.remoterpc.router.zeromq.Message.MessageType;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
-/**
- * ZeroMq based implementation of RpcRouter
- * TODO:
- * 1. Make it multi VM aware
- * 2. Make rpc request handling async and non-blocking. Note zmq socket is not thread safe
- * 3. sendRpc() should use connection pooling
- * 4. Read properties from config file using existing(?) ODL properties framework
- */
-public class ZeroMqRpcRouter implements RpcRouter<QName, QName, InstanceIdentifier, Object> {
-
- private ExecutorService serverPool;
- private static ExecutorService handlersPool;
-
- private Map<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
-
- private ProviderSession brokerSession;
-
- private ZMQ.Context context;
- private ZMQ.Socket publisher;
- private ZMQ.Socket subscriber;
- private ZMQ.Socket replySocket;
-
- private static ZeroMqRpcRouter _instance = new ZeroMqRpcRouter();
-
- private final RpcFacade facade = new RpcFacade();
- private final RpcListener listener = new RpcListener();
-
- private final String localIp = getLocalIpAddress();
-
- private String pubPort = System.getProperty("pub.port");// port on which announcements are sent
- private String subPort = System.getProperty("sub.port");// other controller's pub port
- private String pubIp = System.getProperty("pub.ip"); // other controller's ip
- private String rpcPort = System.getProperty("rpc.port");// port on which RPC messages are received
-
- private Logger _logger = LoggerFactory.getLogger(ZeroMqRpcRouter.class);
-
- //Prevent instantiation
- private ZeroMqRpcRouter() {
- }
-
- public static ZeroMqRpcRouter getInstance() {
- return _instance;
- }
-
- public void start() {
- context = ZMQ.context(2);
- publisher = context.socket(ZMQ.PUB);
- int ret = publisher.bind("tcp://*:" + pubPort);
- // serverPool = Executors.newSingleThreadExecutor();
- serverPool = Executors.newCachedThreadPool();
- handlersPool = Executors.newCachedThreadPool();
- routingTable = new ConcurrentHashMap<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
-
- // Start listening for announce and rpc messages
- serverPool.execute(receive());
-
- brokerSession.addRpcRegistrationListener(listener);
-
- Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
- for (QName rpc : currentlySupported) {
- listener.onRpcImplementationAdded(rpc);
- }
-
- }
-
- public void stop() {
- if (handlersPool != null)
- handlersPool.shutdown();
- if (serverPool != null)
- serverPool.shutdown();
- if (publisher != null) {
- publisher.setLinger(0);
- publisher.close();
- }
- if (replySocket != null) {
- replySocket.setLinger(0);
- replySocket.close();
- }
- if (subscriber != null) {
- subscriber.setLinger(0);
- subscriber.close();
- }
- if (context != null)
- context.term();
-
- }
-
- private Runnable receive() {
- return new Runnable() {
- public void run() {
- try {
- // Bind to RPC reply socket
- replySocket = context.socket(ZMQ.REP);
- replySocket.bind("tcp://*:" + rpcPort);
-
- // Bind to publishing controller
- subscriber = context.socket(ZMQ.SUB);
- String pubAddress = "tcp://" + pubIp + ":" + subPort;
- subscriber.connect(pubAddress);
- _logger.debug("{} Subscribing at[{}]", Thread.currentThread().getName(), pubAddress);
-
- //subscribe for announcements
- //TODO: Message type would be changed. Update this
- subscriber.subscribe(Message.serialize(Message.MessageType.ANNOUNCE));
-
- // Poller enables listening on multiple sockets using a single thread
- ZMQ.Poller poller = new ZMQ.Poller(2);
- poller.register(replySocket, ZMQ.Poller.POLLIN);
- poller.register(subscriber, ZMQ.Poller.POLLIN);
-
- //TODO: Add code to restart the thread after exception
- while (!Thread.currentThread().isInterrupted()) {
-
- poller.poll();
-
- if (poller.pollin(0)) {
- handleRpcCall();
- }
- if (poller.pollin(1)) {
- handleAnnouncement();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- replySocket.setLinger(0);
- replySocket.close();
- subscriber.setLinger(0);
- subscriber.close();
- }
- };
- }
-
- /**
- * @throws IOException
- * @throws ClassNotFoundException
- */
- private void handleAnnouncement() throws IOException, ClassNotFoundException {
-
- _logger.info("Announcement received");
- Message.MessageType topic = (MessageType) Message.deserialize(subscriber.recv());
-
- if (subscriber.hasReceiveMore()) {
- try {
- Message m = (Message) Message.deserialize(subscriber.recv());
- _logger.debug("Announcement message [{}]", m);
-
- // TODO: check on msg type or topic. Both
- // should be same. Need to normalize.
- if (Message.MessageType.ANNOUNCE == m.getType())
- updateRoutingTable(m);
- } catch (IOException | ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
-
- }
-
- /**
- * @throws InterruptedException
- * @throws ExecutionException
- */
- private void handleRpcCall() throws InterruptedException, ExecutionException {
- try {
- Message request = parseMessage(replySocket);
-
- _logger.debug("Received rpc request [{}]", request);
-
- // Call broker to process the message then reply
- Future<RpcResult<CompositeNode>> rpc = brokerSession.rpc(
- (QName) request.getRoute().getType(), (CompositeNode) request.getPayload());
-
- RpcResult<CompositeNode> result = rpc.get();
-
- Message response = new Message.MessageBuilder()
- .type(MessageType.RESPONSE)
- .sender(localIp + ":" + rpcPort)
- .route(request.getRoute())
- //.payload(result) TODO: enable and test
- .build();
-
- replySocket.send(Message.serialize(response));
-
- _logger.debug("Sent rpc response [{}]", response);
-
- } catch (IOException ex) {
- //TODO: handle exception and send error codes to caller
- ex.printStackTrace();
- }
- }
-
-
- @Override
- public Future<RpcReply<Object>> sendRpc(
- final RpcRequest<QName, QName, InstanceIdentifier, Object> input) {
-
- return handlersPool.submit(new Callable<RpcReply<Object>>() {
-
- @Override
- public RpcReply<Object> call() {
- ZMQ.Socket requestSocket = context.socket(ZMQ.REQ);
-
- // TODO pick the ip and port from routing table based on routing identifier
- requestSocket.connect("tcp://" + pubIp + ":5554");
-
- Message requestMessage = new Message.MessageBuilder()
- .type(MessageType.REQUEST)
- .sender(localIp + ":" + rpcPort)
- .route(input.getRoutingInformation())
- .payload(input.getPayload())
- .build();
-
- _logger.debug("Sending rpc request [{}]", requestMessage);
-
- RpcReply<Object> reply = null;
-
- try {
-
- requestSocket.send(Message.serialize(requestMessage));
- final Message response = parseMessage(requestSocket);
-
- _logger.debug("Received response [{}]", response);
-
- reply = new RpcReply<Object>() {
-
- @Override
- public Object getPayload() {
- return response.getPayload();
- }
- };
- } catch (IOException ex) {
- // TODO: Pass exception back to the caller
- ex.printStackTrace();
- }
-
- return reply;
- }
- });
- }
-
- /**
- * TODO: Remove this implementation and use RoutingTable implementation to send announcements
- * Publishes a notice to other controllers in the cluster
- *
- * @param notice
- */
- public void publish(final Message notice) {
- Runnable task = new Runnable() {
- public void run() {
-
- try {
-
- publisher.sendMore(Message.serialize(Message.MessageType.ANNOUNCE));
- publisher.send(Message.serialize(notice));
- _logger.debug("Announcement sent [{}]", notice);
- } catch (IOException ex) {
- _logger.error("Error in sending announcement [{}]", notice);
- ex.printStackTrace();
- }
- }
- };
- handlersPool.execute(task);
- }
-
- /**
- * Finds IPv4 address of the local VM
- * TODO: This method is non-deterministic. There may be more than one IPv4 address. Cant say which
- * address will be returned. Read IP from a property file or enhance the code to make it deterministic.
- * Should we use IP or hostname?
- *
- * @return
- */
- private String getLocalIpAddress() {
- String hostAddress = null;
- Enumeration e = null;
- try {
- e = NetworkInterface.getNetworkInterfaces();
- } catch (SocketException e1) {
- e1.printStackTrace();
- }
- while (e.hasMoreElements()) {
-
- NetworkInterface n = (NetworkInterface) e.nextElement();
-
- Enumeration ee = n.getInetAddresses();
- while (ee.hasMoreElements()) {
- InetAddress i = (InetAddress) ee.nextElement();
- if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
- hostAddress = i.getHostAddress();
- }
- }
- return hostAddress;
-
- }
-
- /**
- * TODO: Change to use external routing table implementation
- *
- * @param msg
- */
- private void updateRoutingTable(Message msg) {
- routingTable.put(msg.getRoute(), msg.getSender());
- RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> route = msg.getRoute();
-
- // Currently only registers rpc implementation.
- // TODO: do registration for instance based routing
- QName rpcType = route.getType();
- RpcRegistration registration = brokerSession.addRpcImplementation(rpcType, facade);
- _logger.debug("Routing table updated");
- }
-
- /**
- * @param socket
- * @return
- */
- private Message parseMessage(ZMQ.Socket socket) {
-
- Message msg = null;
- try {
- byte[] bytes = socket.recv();
- _logger.debug("Received bytes:[{}]", bytes.length);
- msg = (Message) Message.deserialize(bytes);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- return msg;
- }
-
- private class RpcFacade implements RpcImplementation {
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return Collections.emptySet();
- }
-
- @Override
- public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
-
- RouteIdentifierImpl routeId = new RouteIdentifierImpl();
- routeId.setType(rpc);
-
- RpcRequestImpl request = new RpcRequestImpl();
- request.setRouteIdentifier(routeId);
- request.setPayload(input);
-
- final Future<RpcReply<Object>> ret = sendRpc(request);
-
- //TODO: Review result handling
- RpcResult<CompositeNode> result = new RpcResult<CompositeNode>() {
- @Override
- public boolean isSuccessful() {
- try {
- ret.get();
- } catch (InterruptedException | ExecutionException e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- @Override
- public CompositeNode getResult() {
- return null;
- }
-
- @Override
- public Collection<RpcError> getErrors() {
- return Collections.EMPTY_LIST;
- }
- };
- return result;
- }
- }
-
- /**
- * Listener for rpc registrations
- */
- private class RpcListener implements RpcRegistrationListener {
-
- @Override
- public void onRpcImplementationAdded(QName name) {
-
- _logger.debug("Announcing registration for [{}]", name);
- RouteIdentifierImpl routeId = new RouteIdentifierImpl();
- routeId.setType(name);
-
- //TODO: Make notice immutable and change message type
- Message notice = new Message.MessageBuilder()
- .type(MessageType.ANNOUNCE)
- .sender("tcp://" + localIp + ":" + rpcPort)
- .route(routeId)
- .build();
-
- publish(notice);
- }
-
- @Override
- public void onRpcImplementationRemoved(QName name) {
- // TODO: send a rpc-deregistrtation notice
-
- }
- }
-
- public void setBrokerSession(ProviderSession session) {
- this.brokerSession = session;
-
- }
-
-}
+++ /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>
- <artifactId>sal-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
- <groupId>org.opendaylight.controller</groupId>
- </parent>
- <packaging>pom</packaging>
- <groupId>org.opendaylight.controller.tests</groupId>
- <artifactId>sal-test-parent</artifactId>
- <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>
-
- <modules>
- <module>zeromq-test-consumer</module>
- <module>zeromq-test-it</module>
- <module>zeromq-test-provider</module>
- </modules>
-
-</project>
+++ /dev/null
-package org.opendaylight.controller.sample.zeromq.consumer;
-
-import java.net.URI;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import org.opendaylight.controller.sal.core.api.AbstractConsumer;
-import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.osgi.framework.BundleContext;
-
-public class ExampleConsumer extends AbstractConsumer {
-
- private final URI namespace = URI.create("http://cisco.com/example");
- private final QName QNAME = new QName(namespace,"heartbeat");
-
- ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
- private ConsumerSession session;
-
-
- @Override
- public void onSessionInitiated(ConsumerSession session) {
- this.session = session;
- executor.scheduleAtFixedRate(new Runnable() {
-
- @Override
- public void run() {
- int count = 0;
- try {
- Future<RpcResult<CompositeNode>> future = ExampleConsumer.this.session.rpc(QNAME, null);
- RpcResult<CompositeNode> result = future.get();
- System.out.println("Result received. Status is :" + result.isSuccessful());
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
- }, 0, 10, TimeUnit.SECONDS);
- }
-
- @Override
- protected void stopImpl(BundleContext context) {
- // TODO Auto-generated method stub
- super.stopImpl(context);
- executor.shutdown();
- }
-}
+++ /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>
- <artifactId>sal-test-parent</artifactId>
- <groupId>org.opendaylight.controller.tests</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>zeromq-test-it</artifactId>
- <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>
-
- <properties>
- <exam.version>3.0.0</exam.version>
- <url.version>1.5.0</url.version>
- </properties>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>maven-paxexam-plugin</artifactId>
- <version>1.2.4</version>
- <executions>
- <execution>
- <id>generate-config</id>
- <goals>
- <goal>generate-depends-file</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- <pluginManagement>
- <plugins>
- <!--This plugin's configuration is used to store Eclipse m2e settings
- only. It has no influence on the Maven build itself. -->
- <plugin>
- <groupId>org.eclipse.m2e</groupId>
- <artifactId>lifecycle-mapping</artifactId>
- <version>1.0.0</version>
- <configuration>
- <lifecycleMappingMetadata>
- <pluginExecutions>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>
- org.ops4j.pax.exam
- </groupId>
- <artifactId>
- maven-paxexam-plugin
- </artifactId>
- <versionRange>
- [1.2.4,)
- </versionRange>
- <goals>
- <goal>
- generate-depends-file
- </goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <ignore></ignore>
- </action>
- </pluginExecution>
- </pluginExecutions>
- </lifecycleMappingMetadata>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>xtend-lib-osgi</artifactId>
- <version>2.4.3</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.tests</groupId>
- <artifactId>zeromq-test-provider</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.tests</groupId>
- <artifactId>zeromq-test-consumer</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-broker-impl</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-container-native</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-junit4</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-link-mvn</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.osgi</artifactId>
- <version>3.8.1.v20120830-144521</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- <version>1.7.2</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- <version>1.0.9</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <version>1.0.9</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-api</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-core-api</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
-
-
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>containermanager</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-api</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- </dependencies>
-</project>
+++ /dev/null
-package org.opendaylight.controller.sample.zeromq.test.it;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.osgi.framework.BundleContext;
-
-import javax.inject.Inject;
-
-import static org.junit.Assert.assertTrue;
-import static org.ops4j.pax.exam.CoreOptions.*;
-
-@RunWith(PaxExam.class)
-public class ServiceConsumerController {
-
- public static final String ODL = "org.opendaylight.controller";
- public static final String YANG = "org.opendaylight.yangtools";
- public static final String SAMPLE = "org.opendaylight.controller.samples";
-
- @Test
- public void properInitialized() throws Exception {
-
- Thread.sleep(30000); // Waiting for services to get wired.
- assertTrue(true);
- //assertTrue(consumer.createToast(WhiteBread.class, 5));
-
- }
-
-// @Inject
-// BindingAwareBroker broker;
-
-// @Inject
-// ToastConsumer consumer;
-
- @Inject
- BundleContext ctx;
-
- @Configuration
- public Option[] config() {
- return options(systemProperty("osgi.console").value("2401"),
- systemProperty("pub.port").value("5557"),
- systemProperty("sub.port").value("5556"),
- systemProperty("rpc.port").value("5555"),
- systemProperty("pub.ip").value("localhost"),
- mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
- mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
- mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
- mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
-
- //mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject().update(), //
- mavenBundle(ODL, "sal-common").versionAsInProject(), //
- mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
- mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
- mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
- mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
- mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
- mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
- mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
- mavenBundle(SAMPLE, "zeromq-test-consumer").versionAsInProject(), //
- mavenBundle(ODL, "sal-zeromq-connector").versionAsInProject(), //
- mavenBundle(YANG, "concepts").versionAsInProject(),
- mavenBundle(YANG, "yang-binding").versionAsInProject(), //
- mavenBundle(YANG, "yang-common").versionAsInProject(), //
- mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
- mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
- mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
- mavenBundle("com.google.guava", "guava").versionAsInProject(), //
- mavenBundle("org.jeromq", "jeromq").versionAsInProject(),
- junitBundles()
- );
- }
-
-}
+++ /dev/null
-package org.opendaylight.controller.sample.zeromq.test.it;
-
-import static org.junit.Assert.*;
-import static org.ops4j.pax.exam.CoreOptions.junitBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.CoreOptions.systemPackages;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-import static org.ops4j.pax.exam.CoreOptions.maven;
-
-import java.util.Collection;
-
-import javax.inject.Inject;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.CoreOptions;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-@RunWith(PaxExam.class)
-public class ServiceProviderController {
-
- public static final String ODL = "org.opendaylight.controller";
- public static final String YANG = "org.opendaylight.yangtools";
- public static final String SAMPLE = "org.opendaylight.controller.samples";
-
- @Test
- public void properInitialized() throws Exception {
-
- Thread.sleep(30000); // Waiting for services to get wired.
- assertTrue(true);
- //assertTrue(consumer.createToast(WhiteBread.class, 5));
-
- }
-
-// @Inject
-// BindingAwareBroker broker;
-
-// @Inject
-// ToastConsumer consumer;
-
- @Inject
- BundleContext ctx;
-
- @Configuration
- public Option[] config() {
- return options(systemProperty("osgi.console").value("2401"),
- systemProperty("pub.port").value("5556"),
- systemProperty("sub.port").value("5557"),
- systemProperty("rpc.port").value("5554"),
- systemProperty("pub.ip").value("localhost"),
- mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
- mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
- mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
- mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
-
- //mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject().update(), //
- mavenBundle(ODL, "sal-common").versionAsInProject(), //
- mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
- mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
- mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
- mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
- mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
- mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
- mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
- mavenBundle(SAMPLE, "zeromq-test-provider").versionAsInProject(), //
- mavenBundle(ODL, "sal-zeromq-connector").versionAsInProject(), //
- mavenBundle(YANG, "concepts").versionAsInProject(),
- mavenBundle(YANG, "yang-binding").versionAsInProject(), //
- mavenBundle(YANG, "yang-common").versionAsInProject(), //
- mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
- mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
- mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
- mavenBundle("com.google.guava", "guava").versionAsInProject(), //
- mavenBundle("org.jeromq", "jeromq").versionAsInProject(),
- junitBundles()
- );
- }
-
-}
+++ /dev/null
-package org.opendaylight.controller.sample.zeromq.provider;
-
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.osgi.framework.BundleContext;
-
-public class ExampleProvider extends AbstractProvider implements RpcImplementation {
-
- private final URI namespace = URI.create("http://cisco.com/example");
- private final QName QNAME = new QName(namespace,"heartbeat");
- private RpcRegistration reg;
-
-
- @Override
- public void onSessionInitiated(ProviderSession session) {
- //Adding heartbeat 10 times just to make sure subscriber get it
- for (int i=0;i<10;i++){
- System.out.println("ExampleProvider: Adding " + QNAME + " " + i);
- reg = session.addRpcImplementation(QNAME, this);
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
- }
- }
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return Collections.singleton(QNAME);
- }
-
- @Override
- public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
- if(QNAME.equals(rpc)) {
- RpcResult<CompositeNode> output = Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
- return output;
- }
- RpcResult<CompositeNode> output = Rpcs.getRpcResult(false, null, Collections.<RpcError>emptySet());
- return output;
- }
-
- @Override
- protected void stopImpl(BundleContext context) {
- if(reg != null) {
- try {
- reg.close();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
-
-}
<?xml version="1.0" encoding="UTF-8"?>
<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">
+ 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>
<extensions>true</extensions>
<configuration>
<instructions>
-
+ <Export-Package>
+ org.opendaylight.controller.sal.connector.remoterpc.api,
+ org.opendaylight.controller.sal.connector.remoterpc.impl
+ </Export-Package>
<Import-Package>
javax.xml.bind.annotation,
org.opendaylight.controller.sal.core,
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
org.osgi.framework,
org.osgi.util.tracker,
org.slf4j,
- org.w3c.dom
+ org.w3c.dom,
+ com.google.common.io,
+ org.opendaylight.yangtools.yang.model.api.type
</Import-Package>
<Export-Package>
</Export-Package>
import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeType;
if (attributeIfc instanceof JavaAttribute) {
try {
- return caseJavaAttribute(attributeIfc.getOpenType());
+ if(((JavaAttribute)attributeIfc).getTypeDefinition() instanceof BinaryTypeDefinition) {
+ return caseJavaBinaryAttribute(attributeIfc.getOpenType());
+ } else
+ return caseJavaAttribute(attributeIfc.getOpenType());
} catch (UnknownOpenTypeException e) {
throw getIllegalArgumentException(attributeIfc);
}
throw getIllegalArgumentException(attributeIfc);
}
+ protected T caseJavaBinaryAttribute(OpenType<?> openType) {
+ return caseJavaAttribute(openType);
+ }
private IllegalArgumentException getIllegalArgumentException(AttributeIfc attributeIfc) {
return new IllegalArgumentException("Unknown attribute type " + attributeIfc.getClass() + ", " + attributeIfc
@Override
public AttributeConfigElement readElement(List<XmlElement> configNodes) {
if (configNodes.size() == 0)
- return AttributeConfigElement.createNullValue(nullableDefault);
+ return AttributeConfigElement.createNullValue(postprocessNullableDefault(nullableDefault));
return readElementHook(configNodes);
}
abstract AttributeConfigElement readElementHook(List<XmlElement> configNodes);
+ protected Object postprocessNullableDefault(String nullableDefault) {
+ return nullableDefault;
+ }
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
import com.google.common.base.Optional;
-import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
import javax.management.openmbean.OpenType;
}
- public static AttributeConfigElement create(AttributeIfc attributeIfc, Object value) {
- String nullableDefault = attributeIfc.getNullableDefault();
- return create(nullableDefault, value);
- }
-
- public static AttributeConfigElement create(String nullableDefault, Object value) {
+ public static AttributeConfigElement create(Object nullableDefault, Object value) {
return new AttributeConfigElement(nullableDefault, value);
}
- public static AttributeConfigElement createNullValue(AttributeIfc attributeIfc) {
- return new AttributeConfigElement(attributeIfc.getNullableDefault(), null);
- }
-
- public static AttributeConfigElement createNullValue(String nullableDefault) {
+ public static AttributeConfigElement createNullValue(Object nullableDefault) {
return new AttributeConfigElement(nullableDefault, null);
}
-
public Object getValue() {
return value;
}
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import java.util.Map;
import java.util.Map.Entry;
return switchAttribute(attributeIfc);
}
+ @Override
+ protected AttributeReadingStrategy caseJavaBinaryAttribute(OpenType<?> openType) {
+ return new SimpleBinaryAttributeReadingStrategy(lastAttribute.getNullableDefault());
+ }
+
@Override
public AttributeReadingStrategy caseJavaSimpleAttribute(SimpleType<?> openType) {
return new SimpleAttributeReadingStrategy(lastAttribute.getNullableDefault());
String textContent = xmlElement.getTextContent();
Preconditions.checkNotNull(textContent, "This element should contain text %s", xmlElement);
- return AttributeConfigElement.create(getNullableDefault(), postprocessParsedValue(textContent));
+ return AttributeConfigElement.create(postprocessNullableDefault(getNullableDefault()),
+ postprocessParsedValue(textContent));
+ }
+
+ @Override
+ protected Object postprocessNullableDefault(String nullableDefault) {
+ return nullableDefault;
}
protected Object postprocessParsedValue(String textContent) {
--- /dev/null
+/*
+ * 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.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import com.google.common.collect.Lists;
+import com.google.common.io.BaseEncoding;
+
+import java.util.List;
+
+public class SimpleBinaryAttributeReadingStrategy extends SimpleAttributeReadingStrategy {
+
+ public SimpleBinaryAttributeReadingStrategy(String nullableDefault) {
+ super(nullableDefault);
+ }
+
+ protected Object postprocessParsedValue(String textContent) {
+ BaseEncoding en = BaseEncoding.base64();
+ byte[] decode = en.decode(textContent);
+ List<String> parsed = Lists.newArrayListWithCapacity(decode.length);
+ for (byte b : decode) {
+ parsed.add(Byte.toString(b));
+ }
+ return parsed;
+ }
+
+ @Override
+ protected Object postprocessNullableDefault(String nullableDefault) {
+ return nullableDefault == null ? null : postprocessParsedValue(nullableDefault);
+ }
+}
public class SimpleCompositeAttributeReadingStrategy extends SimpleAttributeReadingStrategy {
-
private final String key;
public SimpleCompositeAttributeReadingStrategy(String nullableDefault, String key) {
return map;
}
+ @Override
+ protected Object postprocessNullableDefault(String nullableDefault) {
+ return nullableDefault == null ? null : postprocessParsedValue(nullableDefault);
+ }
}
parsedInnerValue.isPresent() ? parsedInnerValue.get() : null);
}
- CompositeDataSupport parsedValue = null;
+ CompositeDataSupport parsedValue;
try {
parsedValue = new CompositeDataSupport(getOpenType(), items);
} catch (OpenDataException e) {
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import java.util.Map;
import java.util.Map.Entry;
return switchAttribute(expectedAttr);
}
+ @Override
+ protected AttributeWritingStrategy caseJavaBinaryAttribute(OpenType<?> openType) {
+ return new SimpleBinaryAttributeWritingStrategy(document, key);
+ }
+
@Override
protected AttributeWritingStrategy caseJavaSimpleAttribute(SimpleType<?> openType) {
return new SimpleAttributeWritingStrategy(document, key);
--- /dev/null
+/*
+ * 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.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import com.google.common.base.Preconditions;
+import com.google.common.io.BaseEncoding;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.w3c.dom.Document;
+
+import java.util.List;
+
+public class SimpleBinaryAttributeWritingStrategy extends SimpleAttributeWritingStrategy {
+
+ /**
+ * @param document
+ * @param key
+ */
+ public SimpleBinaryAttributeWritingStrategy(Document document, String key) {
+ super(document, key);
+ }
+
+ protected Object preprocess(Object value) {
+ Util.checkType(value, List.class);
+ BaseEncoding en = BaseEncoding.base64();
+
+ List<?> list = (List<?>) value;
+ byte[] decoded = new byte[list.size()];
+ int i = 0;
+ for (Object bAsStr : list) {
+ Preconditions.checkArgument(bAsStr instanceof String, "Unexpected inner value for %s, expected string", value);
+ byte b = Byte.parseByte((String) bAsStr);
+ decoded[i++] = b;
+ }
+
+ return en.encode(decoded);
+ }
+
+}
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.management.InstanceAlreadyExistsException;
edit("netconfMessages/editConfig.xml");
checkBinaryLeafEdited(getConfigCandidate());
+
// default-operation:none, should not affect binary leaf
edit("netconfMessages/editConfig_none.xml");
checkBinaryLeafEdited(getConfigCandidate());
// check after edit
commit();
Element response = getConfigRunning();
- System.err.println(XmlUtil.toString(response));
checkBinaryLeafEdited(response);
checkTypeConfigAttribute(response);
verifyNoMoreInteractions(netconfOperationRouter);
}
+ private void checkBigDecimal(Element response) {
+ String responseTrimmed = XmlUtil.toString(response).replaceAll("\\s", "");
+
+ assertContainsString(responseTrimmed, "<sleep-factorxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">2.58</sleep-factor>");
+ // Default
+ assertContainsString(responseTrimmed, "<sleep-factorxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">2.00</sleep-factor>");
+
+ }
+
private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException,
IOException {
DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID);
edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml");
} catch (NetconfDocumentedException e) {
String message = e.getMessage();
- assertThat(message,
- JUnitMatchers
- .containsString("Element simple-long-2 present multiple times with different namespaces"));
- assertThat(message,
- JUnitMatchers.containsString("urn:opendaylight:params:xml:ns:yang:controller:test:impl"));
- assertThat(message,
- JUnitMatchers
- .containsString(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG));
+ assertContainsString(message, "Element simple-long-2 present multiple times with different namespaces");
+ assertContainsString(message, "urn:opendaylight:params:xml:ns:yang:controller:test:impl");
+ assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
throw e;
}
}
edit("netconfMessages/namespaces/editConfig_differentNamespaceTO.xml");
} catch (NetconfDocumentedException e) {
String message = e.getMessage();
- assertThat(message, JUnitMatchers.containsString("Unrecognised elements"));
- assertThat(message, JUnitMatchers.containsString("simple-int2"));
- assertThat(message, JUnitMatchers.containsString("dto_d"));
+ assertContainsString(message, "Unrecognised elements");
+ assertContainsString(message, "simple-int2");
+ assertContainsString(message, "dto_d");
throw e;
}
}
edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml");
} catch (NetconfDocumentedException e) {
String message = e.getMessage();
- assertThat(message,
- JUnitMatchers.containsString("Element binaryLeaf present multiple times with different namespaces"));
- assertThat(message,
- JUnitMatchers.containsString("urn:opendaylight:params:xml:ns:yang:controller:test:impl"));
- assertThat(message,
- JUnitMatchers
- .containsString(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG));
+ assertContainsString(message, "Element binaryLeaf present multiple times with different namespaces");
+ assertContainsString(message, "urn:opendaylight:params:xml:ns:yang:controller:test:impl");
+ assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
throw e;
}
}
try {
edit(file);
} catch (NetconfDocumentedException e) {
- assertThat(e.getMessage(), JUnitMatchers.containsString("Unrecognised elements"));
- assertThat(e.getMessage(), JUnitMatchers.containsString("unknownAttribute"));
+ assertContainsString(e.getMessage(), "Unrecognised elements");
+ assertContainsString(e.getMessage(), "unknownAttribute");
continue;
}
fail("Unrecognised test should throw exception " + file);
}
private void checkBinaryLeafEdited(final Element response) {
- final NodeList children = response.getElementsByTagName("binaryLeaf");
- assertEquals(3, children.getLength());
- final StringBuffer buf = new StringBuffer();
- for (int i = 0; i < 3; i++) {
- final Element e = (Element) children.item(i);
- buf.append(XmlElement.fromDomElement(e).getTextContent());
- }
- assertEquals("810", buf.toString());
+ String responseTrimmed = XmlUtil.toString(response).replaceAll("\\s", "");
+ String substring = "<binaryLeafxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">YmluYXJ5</binaryLeaf>";
+ assertContainsString(responseTrimmed, substring);
+ substring = "<binaryLeafxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">ZGVmYXVsdEJpbg==</binaryLeaf>";
+ assertContainsString(responseTrimmed, substring);
}
private void checkTypedefs(final Element response) {
- NodeList children = response.getElementsByTagName("extended");
- assertEquals(1, children.getLength());
+ String responseTrimmed = XmlUtil.toString(response).replaceAll("\\s", "");
+
+ String substring = "<extendedxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">10</extended>";
+ assertContainsString(responseTrimmed, substring);
+ // Default
+ assertContainsString(responseTrimmed,
+ "<extendedxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">1</extended>");
- children = response.getElementsByTagName("extended-twice");
- assertEquals(1, children.getLength());
+ assertContainsString(responseTrimmed,
+ "<extended-twicexmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">20</extended-twice>");
+ // Default
+ assertContainsString(responseTrimmed,
+ "<extended-twicexmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">2</extended-twice>");
+
+ assertContainsString(responseTrimmed,
+ "<extended-enumxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">TWO</extended-enum>");
+ // Default
+ assertContainsString(responseTrimmed,
+ "<extended-enumxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">ONE</extended-enum>");
+ }
+
+ private void assertContainsString(String string, String substring) {
+ assertThat(string, JUnitMatchers.containsString(substring));
}
private void checkEnum(final Element response) {
assertEquals(2, testingDepsSize);
}
- private void checkBigDecimal(Element response) {
- int size = response.getElementsByTagName("sleep-factor").getLength();
- assertEquals(1, size);
- }
-
-
private void checkTypeConfigAttribute(Element response) {
XmlElement modulesElement = XmlElement.fromDomElement(response).getOnlyChildElement("data")
RuntimeRpc netconf = new RuntimeRpc(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID);
response = executeOp(netconf, "netconfMessages/rpc.xml");
- assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("testarg1".toUpperCase()));
+ assertContainsString(XmlUtil.toString(response), "testarg1".toUpperCase());
response = executeOp(netconf, "netconfMessages/rpcInner.xml");
- assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("ok"));
+ assertContainsString(XmlUtil.toString(response), "ok");
response = executeOp(netconf, "netconfMessages/rpcInnerInner.xml");
- assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("true"));
+ assertContainsString(XmlUtil.toString(response), "true");
response = executeOp(netconf, "netconfMessages/rpcInnerInner_complex_output.xml");
- assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("1"));
- assertThat(XmlUtil.toString(response), JUnitMatchers.containsString("2"));
+ assertContainsString(XmlUtil.toString(response), "1");
+ assertContainsString(XmlUtil.toString(response), "2");
}
private Element get() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException {
<name>test1</name>
<sleep-factor>
- 2.00
+ 2.58
</sleep-factor>
<extended>
- 1
+ 10
</extended>
<extended-twice>
- 1
+ 20
</extended-twice>
<extended-enum>
</extended-enum>
<simple-long-2>44</simple-long-2>
- <binaryLeaf>8</binaryLeaf>
- <binaryLeaf>1</binaryLeaf>
- <binaryLeaf>0</binaryLeaf>
+ <binaryLeaf>YmluYXJ5</binaryLeaf>
+
<type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
<dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
<simple-int1>444</simple-int1>
</type>
<name>test1</name>
<simple-long-2>44</simple-long-2>
- <binaryLeaf>8</binaryLeaf>
- <binaryLeaf>7</binaryLeaf>
- <binaryLeaf>9</binaryLeaf>
+ <binaryLeaf>8ad1</binaryLeaf>
<dto_d>
<simple-int1>444</simple-int1>
<simple-int2>4444</simple-int2>
<name>test1</name>
<simple-long-2>44</simple-long-2>
- <binaryLeaf>8</binaryLeaf>
- <binaryLeaf>1</binaryLeaf>
- <binaryLeaf>0</binaryLeaf>
+ <binaryLeaf>8545649856</binaryLeaf>
<type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
<dto_d>
<simple-int1>444</simple-int1>
<name>test1</name>
<simple-long-2>44</simple-long-2>
- <binaryLeaf>8</binaryLeaf>
- <binaryLeaf>1</binaryLeaf>
- <binaryLeaf>0</binaryLeaf>
+ <binaryLeaf>8545649856</binaryLeaf>
<dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
<simple-int1>444</simple-int1>
<simple-int2>4444</simple-int2>
<name>test1</name>
<simple-long-2>44</simple-long-2>
- <binaryLeaf>8</binaryLeaf>
- <binaryLeaf>1</binaryLeaf>
- <binaryLeaf>0</binaryLeaf>
+ <binaryLeaf>8545649856</binaryLeaf>
<dto_d>
<unknownAttribute>error</unknownAttribute>
<simple-int1>444</simple-int1>
<name>test1</name>
<simple-long-2>44</simple-long-2>
- <binaryLeaf>8</binaryLeaf>
- <binaryLeaf>1</binaryLeaf>
- <binaryLeaf>0</binaryLeaf>
+ <binaryLeaf>8545649856</binaryLeaf>
<dto_d>
<simple-int1>444</simple-int1>
<simple-int2>4444</simple-int2>
import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.utils.EtherTypes;
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.NodeCreator;
action, "Invalid node type"));
}
+ Status status = validateFlow(flow);
+ if (!status.isSuccess()) {
+ return status;
+ }
+
if (controller != null) {
ISwitch sw = controller.getSwitch((Long) node.getID());
if (sw != null) {
"Internal plugin error"));
}
+ /*
+ * Method which runs openflow 1.0 specific validation on the requested flow
+ * This validation is needed because the openflow switch will silently accept
+ * the request and install only the applicable match fields
+ */
+ private Status validateFlow(Flow flow) {
+ Match m = flow.getMatch();
+ boolean isIPEthertypeSet = m.isPresent(MatchType.DL_TYPE)
+ && (m.getField(MatchType.DL_TYPE).getValue().equals(EtherTypes.IPv4.shortValue()) || m
+ .getField(MatchType.DL_TYPE).getValue().equals(EtherTypes.IPv6.shortValue()));
+
+ // network address check
+ if ((m.isPresent(MatchType.NW_SRC) || m.isPresent(MatchType.NW_DST)) && !isIPEthertypeSet) {
+ return new Status(StatusCode.NOTACCEPTABLE,
+ "The match on network source or destination address cannot be accepted if the match "
+ + "on proper ethertype is missing");
+ }
+
+ // transport protocol check
+ if (m.isPresent(MatchType.NW_PROTO) && !isIPEthertypeSet) {
+ return new Status(StatusCode.NOTACCEPTABLE,
+ "The match on network protocol cannot be accepted if the match on proper ethertype is missing");
+ }
+
+ // transport ports check
+ if ((m.isPresent(MatchType.TP_SRC) || m.isPresent(MatchType.TP_DST))
+ && (!isIPEthertypeSet || m.isAny(MatchType.NW_PROTO))) {
+ return new Status(
+ StatusCode.NOTACCEPTABLE,
+ "The match on transport source or destination port cannot be accepted if the match on network protocol and match on IP ethertype are missing");
+ }
+ return new Status(StatusCode.SUCCESS);
+ }
+
private Status modifyFlowInternal(Node node, Flow oldFlow, Flow newFlow, long rid) {
String action = "modify";
if (!node.getType().equals(NodeIDType.OPENFLOW)) {
return new Status(StatusCode.NOTACCEPTABLE, errorString("send",
action, "Invalid node type"));
}
+
+ Status status = validateFlow(newFlow);
+ if (!status.isSuccess()) {
+ return status;
+ }
+
if (controller != null) {
ISwitch sw = controller.getSwitch((Long) node.getID());
if (sw != null) {
package org.opendaylight.controller.protocol_plugin.openflow.internal;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
@Override
public void switchAdded(ISwitch sw) {
if (sw == null) {
+ logger.debug("Ignore null switch addition");
return;
}
Node node = NodeCreator.createOFNode(sw.getId());
return;
}
- // Add all the nodeConnectors of this switch
- Map<NodeConnector, Set<Property>> ncProps = InventoryServiceHelper
- .OFSwitchToProps(sw);
- for (Map.Entry<NodeConnector, Set<Property>> entry : ncProps.entrySet()) {
- Set<Property> props = new HashSet<Property>();
- Set<Property> prop = entry.getValue();
- if (prop != null) {
- props.addAll(prop);
+ // Add all the nodeConnectors of this switch if any
+ Map<NodeConnector, Set<Property>> ncProps = InventoryServiceHelper.OFSwitchToProps(sw);
+ if (!ncProps.isEmpty()) {
+ for (Map.Entry<NodeConnector, Set<Property>> entry : ncProps.entrySet()) {
+ Set<Property> props = new HashSet<Property>();
+ Set<Property> prop = entry.getValue();
+ if (prop != null) {
+ props.addAll(prop);
+ }
+ nodeConnectorProps.put(entry.getKey(), props);
+ notifyInventoryShimListener(entry.getKey(), UpdateType.ADDED, entry.getValue());
}
- nodeConnectorProps.put(entry.getKey(), props);
- notifyInventoryShimListener(entry.getKey(), UpdateType.ADDED, entry.getValue());
+ } else {
+ /*
+ * If no node connector is present, publish the node addition itself
+ * in order to let Connection Manager properly set the node locality
+ */
+ this.notifyInventoryShimListener(node, UpdateType.ADDED, Collections.<Property>emptySet());
}
// Add this node
result = prime * result + activeCount;
result = prime * result + (int) (lookupCount ^ (lookupCount >>> 32));
result = prime * result + (int) (matchedCount ^ (matchedCount >>> 32));
+ result = prime * result + maximumEntries;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((nodeTable == null) ? 0 : nodeTable.hashCode());
return result;
if (matchedCount != other.matchedCount) {
return false;
}
+ if (maximumEntries != other.maximumEntries) {
+ return false;
+ }
if (name == null) {
if (other.name != null) {
return false;
/**
* @return the maximumEntries
*/
- public long getMaximumEntries() {
+ public int getMaximumEntries() {
return maximumEntries;
}
return "NodeTableStats[tableId = " + nodeTable
+ ", activeCount = " + activeCount
+ ", lookupCount = " + lookupCount
- + ", matchedCount = " + matchedCount + "]";
+ + ", matchedCount = " + matchedCount
+ + ", maximumEntries = " + maximumEntries + "]";
}
}
if (!status.isSuccess()) {
return status;
}
+ } else {
+ if (conf.getName().equals(DEFAULT_SUBNET_NAME)) {
+ return new Status(StatusCode.NOTALLOWED, "The specified subnet gateway cannot be removed");
+ }
}
// Update Database
@Override
public Status removeSubnet(String name) {
+ if (name.equals(DEFAULT_SUBNET_NAME)) {
+ return new Status(StatusCode.NOTALLOWED, "The specified subnet gateway cannot be removed");
+ }
SubnetConfig conf = subnetsConfigList.get(name);
if (conf == null) {
return new Status(StatusCode.SUCCESS, "Subnet not present");
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Configuration Java Object which represents a Local AAA user configuration
@XmlAccessorType(XmlAccessType.NONE)
public class UserConfig implements Serializable {
private static final long serialVersionUID = 1L;
+ private static Logger log = LoggerFactory.getLogger(UserConfig.class);
+ private static final boolean strongPasswordCheck = Boolean.getBoolean("enableStrongPasswordCheck");
+ private static final String DIGEST_ALGORITHM = "SHA-384";
+ private static final String BAD_PASSWORD = "Bad Password";
+ private static final int USERNAME_MAXLENGTH = 32;
+ protected static final String PASSWORD_REGEX = "(?=.*[^a-zA-Z0-9])(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,256}$";
+ private static final Pattern INVALID_USERNAME_CHARACTERS = Pattern.compile("([/\\s\\.\\?#%;\\\\]+)");
+ private static MessageDigest oneWayFunction;
+
+ static {
+ try {
+ UserConfig.oneWayFunction = MessageDigest.getInstance(DIGEST_ALGORITHM);
+ } catch (NoSuchAlgorithmException e) {
+ log.error(String.format("Implementation of %s digest algorithm not found: %s", DIGEST_ALGORITHM,
+ e.getMessage()));
+ }
+ }
/**
* User Id
* example
* System-Admin
* Network-Admin
- * Netowrk-Operator
+ * Network-Operator
*/
@XmlElement
protected List<String> roles;
@XmlElement
private String password;
- private static final boolean strongPasswordCheck = Boolean.getBoolean("enableStrongPasswordCheck");
- private static final String BAD_PASSWORD = "Bad Password";
- private static final int USERNAME_MAXLENGTH = 32;
- protected static final String PASSWORD_REGEX = "(?=.*[^a-zA-Z0-9])(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,256}$";
- private static final Pattern INVALID_USERNAME_CHARACTERS = Pattern.compile("([/\\s\\.\\?#%;\\\\]+)");
- private static MessageDigest oneWayFunction = null;
- static {
- try {
- UserConfig.oneWayFunction = MessageDigest.getInstance("SHA-1");
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- }
public UserConfig() {
}
}
Map<String, Object> nodes = new HashMap<String, Object>();
- Map<Short, String> port;
+ Map<String, String> port;
for (Switch node : switchManager.getNetworkDevices()) {
- port = new HashMap<Short, String>(); // new port
+ port = new HashMap<String, String>(); // new port
Set<NodeConnector> nodeConnectorSet = node.getNodeConnectors();
if (nodeConnectorSet != null) {
for (NodeConnector nodeConnector : nodeConnectorSet) {
String nodeConnectorName = ((Name) switchManager.getNodeConnectorProp(nodeConnector,
Name.NamePropName)).getValue();
- port.put((Short) nodeConnector.getID(),
+ port.put( nodeConnector.getID().toString(),
nodeConnectorName + "(" + nodeConnector.getNodeConnectorIDString() + ")");
}
}
return gson.toJson(result);
}
- @RequestMapping("/users")
+ @RequestMapping(value = "/users", method = RequestMethod.GET)
@ResponseBody
- public List<UserConfig> getUsers() {
+ public List<UserBean> getUsers() {
IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
if (userManager == null) {
return null;
}
- List<UserConfig> userConfList = userManager.getLocalUserList();
+ List<UserBean> result = new ArrayList<UserBean>();
+ List<UserConfig> configs = userManager.getLocalUserList();
+ for (UserConfig config : configs) {
+ UserBean bean = new UserBean(config);
+ result.add(bean);
+ }
- return userConfList;
+ return result;
}
/*
--- /dev/null
+package org.opendaylight.controller.web;
+
+import java.util.List;
+
+import org.opendaylight.controller.usermanager.UserConfig;
+
+public class UserBean {
+ private String user;
+ private List<String> roles;
+
+ public UserBean(String user, List<String> roles) {
+ this.user = user;
+ this.roles = roles;
+ }
+
+ public UserBean(UserConfig config) {
+ this(config.getUser(), config.getRoles());
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public List<String> getRoles() {
+ return roles;
+ }
+}
\ No newline at end of file