<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
</scm>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<dependencies>
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
*/
void tbegin() throws NotSupportedException, SystemException;
+ /**
+ * tbegin with a timeout
+ * @see IClusterServices#tbegin
+ * @param timeout the transaction timeout
+ * @param unit TimeUnit for the timeout
+ * @throws NotSupportedException
+ * @throws SystemException
+ */
+ void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException;
+
/**
* Commit a transaction covering all the data structures/HW updates.
*/
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
*/
void tbegin() throws NotSupportedException, SystemException;
+ /**
+ * tbegin with a timeout
+ * @see IClusterServicesCommon#tbegin
+ * @param timeout the transaction timeout
+ * @param unit TimeUnit for the timeout
+ * @throws NotSupportedException
+ * @throws SystemException
+ */
+ void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException;
+
/**
* Commit a transaction covering all the data structures/HW updates.
*/
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
private static String loopbackAddress = "127.0.0.1";
+ // defaultTransactionTimeout is 60 seconds
+ private static int DEFAULT_TRANSACTION_TIMEOUT = 60;
+
/**
* Start a JGroups GossipRouter if we are a supernode. The
* GosispRouter is nothing more than a simple
@Override
public void tbegin() throws NotSupportedException, SystemException {
+ // call tbegin with the default timeout
+ tbegin(DEFAULT_TRANSACTION_TIMEOUT, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException {
EmbeddedCacheManager manager = this.cm;
if (manager == null) {
throw new IllegalStateException();
if (tm == null) {
throw new IllegalStateException();
}
+ long timeoutSec = unit.toSeconds(timeout);
+ if((timeoutSec > Integer.MAX_VALUE) || (timeoutSec <= 0)) {
+ // fall back to the default timeout
+ tm.setTransactionTimeout(DEFAULT_TRANSACTION_TIMEOUT);
+ } else {
+ // cast is ok here
+ // as here we are sure that timeoutSec < = Integer.MAX_VALUE.
+ tm.setTransactionTimeout((int) timeoutSec);
+ }
tm.begin();
}
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
+
import org.apache.felix.dm.Component;
import org.opendaylight.controller.clustering.services.CacheConfigException;
import org.opendaylight.controller.clustering.services.CacheExistException;
}
}
+ @Override
+ public void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException {
+ if (this.clusterService != null) {
+ this.clusterService.tbegin(timeout, unit);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
@Override
public void tcommit() throws RollbackException, HeuristicMixedException,
HeuristicRollbackException, java.lang.SecurityException,
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
package org.opendaylight.controller.clustering.stub.internal;
-import java.util.ArrayList;
-import java.util.concurrent.ConcurrentHashMap;
-import java.net.UnknownHostException;
import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Dictionary;
import java.util.List;
import java.util.Properties;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
+import org.apache.felix.dm.Component;
import org.opendaylight.controller.clustering.services.CacheConfigException;
import org.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterServices;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Dictionary;
-import org.apache.felix.dm.Component;
-
public abstract class ClusterManagerCommon implements IClusterServicesCommon {
protected String containerName = "";
protected static final Logger logger = LoggerFactory
java.lang.IllegalStateException, SystemException {
}
+ @Override
+ public void tbegin(long timeout, TimeUnit unit) throws NotSupportedException, SystemException {
+
+ }
+
@Override
public void trollback() throws java.lang.IllegalStateException,
java.lang.SecurityException, SystemException {
<yang.version>0.5.9-SNAPSHOT</yang.version>
<guava.version>14.0.1</guava.version>
<osgi.core.version>5.0.0</osgi.core.version>
- <ietf-inet-types.version>2010.09.24.1</ietf-inet-types.version>
- <ietf-yang-types.version>2010.09.24.1</ietf-yang-types.version>
+ <ietf-inet-types.version>2010.09.24.2-SNAPSHOT</ietf-inet-types.version>
+ <ietf-yang-types.version>2010.09.24.2-SNAPSHOT</ietf-yang-types.version>
<opendaylight-l2-types.version>2013.08.27.1</opendaylight-l2-types.version>
<yang-ext.version>2013.09.07.1</yang-ext.version>
<javassist.version>3.17.1-GA</javassist.version>
<sonar.language>java</sonar.language>
<forwardingrulesmanager.version>0.5.0-SNAPSHOT</forwardingrulesmanager.version>
<statisticsmanager.version>0.5.0-SNAPSHOT</statisticsmanager.version>
+ <clustering.services.version>0.5.0-SNAPSHOT</clustering.services.version>
<maven.compile.plugin.version>2.5.1</maven.compile.plugin.version>
<java.version.source>1.7</java.version.source>
<java.version.target>1.7</java.version.target>
<module>netty-event-executor-config</module>
<module>netty-timer-config</module>
<module>config-persister-directory-adapter</module>
+ <module>yang-test-plugin</module>
</modules>
<profiles>
</generator>
<generator>
<codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
- <outputBaseDir>target/site</outputBaseDir>
+ <outputBaseDir>target/site/models</outputBaseDir>
</generator>
</codeGenerators>
<inspectDependencies>true</inspectDependencies>
--- /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">
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-plugin-parent</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ <relativePath>../config-plugin-parent</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>maven-plugin</packaging>
+ <artifactId>yang-test-plugin</artifactId>
+
+ <description>Remove generated source files, after new files generation, implementation is inserted.</description>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>3.0.5</version>
+ </dependency>
+ </dependencies>
+</project>
\ 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.config.yang.test.plugin;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import java.io.File;
+
+/**
+ * Delete all Module/ModuleFactory sources
+ *
+ * @goal delete-sources
+ *
+ * @phase initialize
+ */
+public class DeleteSources extends AbstractMojo{
+ /**
+ * @parameter expression="${project.build.sourceDirectory}"
+ * @readOnly
+ * @required
+ */
+ private File directory;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ if (directory == null || !directory.exists()) {
+ super.getLog().error("Directory does not exists.");
+ }
+ File sourceDirectory = new File(directory.getPath() + Util.replaceDots(".org.opendaylight.controller.config.yang.test.impl"));
+ if (sourceDirectory == null || !sourceDirectory.exists()) {
+ super.getLog().error("Source directory does not exists " + sourceDirectory.getPath());
+ }
+ File[] sourceFiles = sourceDirectory.listFiles();
+ for (File sourceFile: sourceFiles) {
+ if(sourceFile.getName().endsWith("Module.java") || sourceFile.getName().endsWith("ModuleFactory.java")) {
+ super.getLog().debug("Source file deleted: " + sourceFile.getName());
+ sourceFile.delete();
+ }
+ }
+ }
+}
--- /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.config.yang.test.plugin;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+
+/**
+ * Add implementation code from stub.txt
+ *
+ * @goal process-sources
+ *
+ * @phase process-sources
+ *
+ */
+public class ProcessSources extends AbstractMojo{
+ /**
+ * @parameter expression="${project.build.sourceDirectory}"
+ * @readOnly
+ * @required
+ */
+ private File directory;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ if (directory == null || !directory.exists()) {
+ super.getLog().error("Directory does not exists.");
+ }
+ File sourceDirectory = new File(directory.getPath() + Util.replaceDots(".org.opendaylight.controller.config.yang.test.impl"));
+ if (!sourceDirectory.exists()) {
+ super.getLog().error("Source directory does not exists " + sourceDirectory.getPath());
+ }
+ String header = "";
+ try {
+ header = Util.loadHeader();
+ } catch (IOException e) {
+ super.getLog().error("Header.txt not found.");
+ }
+ File[] sourceFiles = sourceDirectory.listFiles();
+ for (File sourceFile: sourceFiles) {
+ if(sourceFile.getName().endsWith("Module.java") || sourceFile.getName().endsWith("ModuleFactory.java")) {
+ File stubFile = new File(sourceFile.getPath().replace(".java", "Stub.txt"));
+ String stubLines = null;
+ try {
+ if (stubFile.exists()) {
+ stubLines = Util.loadStubFile(stubFile.getPath());
+ }
+
+ InputStream javaIn = new FileInputStream(sourceFile.getPath());
+ BufferedReader javaBuf = new BufferedReader(new InputStreamReader(javaIn));
+ StringBuffer output = new StringBuffer();
+ String line = javaBuf.readLine();
+ boolean writeLine = false;
+ while ((line = javaBuf.readLine()) != null) {
+ if(!writeLine && line.contains("*/")) {
+ line = header;
+ writeLine = true;
+ } else {
+ if (line.contains("TODO")) {
+ writeLine = false;
+ } else {
+ if (stubLines != null && line.contains("throw new")) {
+ line = stubLines.toString();
+ writeLine = true;
+ }
+ }
+ }
+ if(writeLine) {
+ output.append(line).append(System.lineSeparator());
+ }
+ }
+ javaBuf.close();
+
+ OutputStream javaOut = new FileOutputStream(sourceFile.getPath());
+ javaOut.write(output.toString().getBytes());
+ javaOut.close();
+ } catch (IOException e) {
+ getLog().error("Error while reading/writing to files.", e);
+ }
+
+ }
+ }
+ }
+}
--- /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.config.yang.test.plugin;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.regex.Matcher;
+
+public class Util {
+
+ public static String replaceDots(String path) {
+ path = path.replace(".", Matcher.quoteReplacement(File.separator));
+ return path;
+ }
+
+ public static String loadHeader() throws IOException {
+ StringBuffer header = new StringBuffer();
+ InputStream headIn = Util.class.getClassLoader().getResourceAsStream("Header.txt");
+ BufferedReader headBuf = new BufferedReader(new InputStreamReader(headIn));
+ String line = null;
+ while ((line = headBuf.readLine()) != null) {
+ header.append(line).append(System.lineSeparator());
+ }
+ headBuf.close();
+ return header.toString();
+ }
+
+ public static String loadStubFile(String fileName) throws IOException {
+ InputStream stubIn = new FileInputStream(fileName);
+ BufferedReader stubBuf = new BufferedReader(new InputStreamReader(stubIn));
+
+ StringBuffer stubLines = new StringBuffer();
+ String stubLine = null;
+ while ((stubLine = stubBuf.readLine()) != null) {
+ stubLines.append(stubLine).append(System.lineSeparator());
+ }
+ stubBuf.close();
+ return stubLines.toString();
+ }
+}
--- /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
+ */
\ No newline at end of file
</dependency>
</dependencies>
</plugin>
+ <plugin>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-test-plugin</artifactId>
+ <version>${config.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>delete-sources</goal>
+ <goal>process-sources</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
</project>
+/*
+ * 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.config.yang.test.impl;
/**
public void close() throws Exception {
}
};
+
}
}
+/*
+ * 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.config.yang.test.impl;
/**
+/*
+ * 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.config.yang.test.impl;
/**
@Override
public java.lang.AutoCloseable createInstance() {
- return NetconfTestImplModuleUtil.registerRuntimeBeans(this);
+return NetconfTestImplModuleUtil.registerRuntimeBeans(this);
+
}
}
+/*
+ * 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.config.yang.test.impl;
/**
-/**
- * @author Tomas Olvecky
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
- * 11 2013
- *
- * Copyright (c) 2013 by Cisco Systems, Inc.
- * 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.config.yang.test.impl;
+/*
+ * 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.config.yang.test.impl;
/**
public void close() throws Exception {
}
};
+
}
}
+/*
+ * 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.config.yang.test.impl;
/**
type tt:extend-enum;
}
+ leaf sleep-factor {
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+
container dto-c {
leaf simple-arg {
type uint32;
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>${controller.version}</version>
+ <version>${clustering.services.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<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-eventexecutor']/instance[name='global-event-executor']</provider>
+ <provider>/config/modules/module[name='netty-global-event-executor']/instance[name='global-event-executor']</provider>
</instance>
</service>
<service>
<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>
+ <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>
//SERVICES START
<service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <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>
+ <name>ref_yang-schema-service</name>
+ <provider>/config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']</provider>
</instance>
</service>
<service>
<provider>/config/modules/module[name='binding-broker-impl']/instance[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>
+ </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>
<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>
+ <name>ref_binding-data-broker</name>
+ <provider>/config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']</provider>
+ </instance>
</service>
//CAPABILITIES START
urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27
}
if (add) {
+ // there may be an already existing entry.
+ // remove it before adding the new one.
+ // This is necessary since we have observed that in some cases
+ // Infinispan does aggregation for operations (eg:- remove and then put a different value)
+ // related to the same key within the same transaction.
+ // Need this defensive code as the new FlowEntryInstall may be different
+ // than the old one even though the equals method returns true. This is because
+ // the equals method does not take into account the action list.
+ if(nodeIndeces.contains(flowEntries)) {
+ nodeIndeces.remove(flowEntries);
+ }
nodeIndeces.add(flowEntries);
} else {
nodeIndeces.remove(flowEntries);
}
if (add) {
+ // same comments in the similar code section in
+ // updateNodeFlowsDB method apply here too
+ if(indices.contains(flowEntries)) {
+ indices.remove(flowEntries);
+ }
indices.add(flowEntries);
} else {
indices.remove(flowEntries);
if (policyName != null && !policyName.trim().isEmpty()) {
for (Map.Entry<FlowEntry, FlowEntry> entry : this.originalSwView.entrySet()) {
if (policyName.equals(entry.getKey().getGroupName())) {
- list.add(entry.getKey().clone());
+ list.add(entry.getValue().clone());
}
}
}
if (policyName != null && !policyName.trim().isEmpty()) {
for (Map.Entry<FlowEntryInstall, FlowEntryInstall> entry : this.installedSwView.entrySet()) {
if (policyName.equals(entry.getKey().getGroupName())) {
- list.add(entry.getKey().getInstall().clone());
+ list.add(entry.getValue().getInstall().clone());
}
}
}
// replay the installedSwView data structure to populate
// node flows and group flows
- for (FlowEntryInstall fei : installedSwView.keySet()) {
+ for (FlowEntryInstall fei : installedSwView.values()) {
pendingEvents.offer(new UpdateIndexDBs(fei, true));
}
* Streamline the updates for the per node and per group index databases
*/
if (cacheName.equals(INSTALLED_SW_VIEW_CACHE)) {
- pendingEvents.offer(new UpdateIndexDBs((FlowEntryInstall)key, true));
+ pendingEvents.offer(new UpdateIndexDBs((FlowEntryInstall)new_value, true));
}
if (originLocal) {
if (node != null) {
for (Map.Entry<FlowEntry, FlowEntry> entry : this.originalSwView.entrySet()) {
if (node.equals(entry.getKey().getNode())) {
- list.add(entry.getKey().clone());
+ list.add(entry.getValue().clone());
}
}
}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
</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>
<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>
private static NotificationService notificationService;
private FlowConsumerImpl flowImplRef;
private GroupConsumerImpl groupImplRef;
+ private MeterConsumerImpl meterImplRef;
private static DataProviderService dataProviderService;
-
- private static IClusterContainerServices clusterContainerService = null;
- private static IContainer container;
-
- @Override
+ private static IClusterContainerServices clusterContainerService = null;
+ private static IContainer container;
+
+ @Override
public void onSessionInitiated(ProviderContext session) {
-
FRMConsumerImpl.p_session = session;
if (!getDependentModule()) {
if (null != dataProviderService) {
flowImplRef = new FlowConsumerImpl();
- // groupImplRef = new GroupConsumerImpl();
+ groupImplRef = new GroupConsumerImpl();
+ meterImplRef = new MeterConsumerImpl();
registerWithOSGIConsole();
} else {
logger.error("Data Provider Service is down or NULL. "
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
bundleContext.registerService(CommandProvider.class.getName(), this, null);
}
-
- private boolean getDependentModule() {
- do {
- clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(IClusterContainerServices.class, this);
- try {
- Thread.sleep(4);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } while(clusterContainerService == null);
-
- do {
-
-
- container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
- try {
- Thread.sleep(5);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } while (container == null);
-
-
- return true;
- }
-
+ private boolean getDependentModule() {
+ do {
+ clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(
+ IClusterContainerServices.class, this);
+ try {
+ Thread.sleep(4);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } while (clusterContainerService == null);
+
+ do {
+
+ container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } while (container == null);
+
+ return true;
+ }
public static DataProviderService getDataProviderService() {
return dataProviderService;
}
public GroupConsumerImpl getGroupImplRef() {
- return groupImplRef;
+ return groupImplRef;
}
-
public static ProviderContext getProviderSession() {
return p_session;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
import org.opendaylight.controller.sal.utils.IPProtocols;
+import org.opendaylight.controller.sal.utils.NetUtils;
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.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.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
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.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.Layer3Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
+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.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.list.Instruction;
public class FRMUtil {
protected static final Logger logger = LoggerFactory.getLogger(FRMUtil.class);
ADD, DELETE, UPDATE, GET
};
+ private enum EtherIPType {
+ ANY, V4, V6;
+ };
+
public static boolean isNameValid(String name) {
// Name validation
}
public static boolean validateMatch(Flow flow) {
+ EtherIPType etype = EtherIPType.ANY;
+ EtherIPType ipsrctype = EtherIPType.ANY;
+ EtherIPType ipdsttype = EtherIPType.ANY;
+
Match match = flow.getMatch();
if (match != null) {
EthernetMatch ethernetmatch = match.getEthernetMatch();
IpMatch ipmatch = match.getIpMatch();
+ Layer3Match layer3match = match.getLayer3Match();
VlanMatch vlanmatch = match.getVlanMatch();
match.getIcmpv4Match();
if (ethernetmatch != null) {
if ((ethernetmatch.getEthernetSource() != null)
- && !isL2AddressValid(ethernetmatch.getEthernetSource().toString())) {
+ && !isL2AddressValid(ethernetmatch.getEthernetSource().getAddress().getValue())) {
- logger.error("Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
+ logger.error("Ethernet source address is not valid. Example: 00:05:b9:7c:81:5f",
ethernetmatch.getEthernetSource());
return false;
}
if ((ethernetmatch.getEthernetDestination() != null)
- && !isL2AddressValid(ethernetmatch.getEthernetDestination().toString())) {
- logger.error("Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
+ && !isL2AddressValid(ethernetmatch.getEthernetDestination().getAddress().getValue())) {
+ logger.error("Ethernet destination address is not valid. Example: 00:05:b9:7c:81:5f",
ethernetmatch.getEthernetDestination());
return false;
}
if (ethernetmatch.getEthernetType() != null) {
- int type = Integer.decode(ethernetmatch.getEthernetType().toString());
+ long type = ethernetmatch.getEthernetType().getType().getValue().longValue();
if ((type < 0) || (type > 0xffff)) {
logger.error("Ethernet type is not valid");
return false;
+ } else {
+ if (type == 0x0800) {
+ etype = EtherIPType.V4;
+ } else if (type == 0x86dd) {
+ etype = EtherIPType.V6;
+ }
+ }
+
+ }
+ }
+
+ if (layer3match != null) {
+ if (layer3match instanceof Ipv4Match) {
+ if (((Ipv4Match) layer3match).getIpv4Source() != null) {
+ if (NetUtils.isIPv4AddressValid(((Ipv4Match) layer3match).getIpv4Source().getValue())) {
+ ipsrctype = EtherIPType.V4;
+ } else {
+ logger.error("IP source address is not valid");
+ return false;
+ }
+
+ } else if (((Ipv4Match) layer3match).getIpv4Destination() != null) {
+ if (NetUtils.isIPv4AddressValid(((Ipv4Match) layer3match).getIpv4Destination().getValue())) {
+ ipdsttype = EtherIPType.V4;
+ } else {
+ logger.error("IP Destination address is not valid");
+ return false;
+ }
+
+ }
+ } else if (layer3match instanceof Ipv6Match) {
+ if (((Ipv6Match) layer3match).getIpv6Source() != null) {
+ if (NetUtils.isIPv6AddressValid(((Ipv6Match) layer3match).getIpv6Source().getValue())) {
+ ipsrctype = EtherIPType.V6;
+ } else {
+ logger.error("IPv6 source address is not valid");
+ return false;
+ }
+
+ } else if (((Ipv6Match) layer3match).getIpv6Destination() != null) {
+ if (NetUtils.isIPv6AddressValid(((Ipv6Match) layer3match).getIpv6Destination().getValue())) {
+ ipdsttype = EtherIPType.V6;
+ } else {
+ logger.error("IPv6 Destination address is not valid");
+ return false;
+ }
+
+ }
+
+ }
+
+ if (etype != EtherIPType.ANY) {
+ if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
+ logger.error("Type mismatch between Ethernet & Src IP");
+ return false;
+ }
+ if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
+ logger.error("Type mismatch between Ethernet & Dst IP");
+ return false;
+ }
+ }
+ if (ipsrctype != ipdsttype) {
+ if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
+ logger.error("IP Src Dest Type mismatch");
+ return false;
}
}
- } else if (ipmatch != null) {
- if (ipmatch.getIpProtocol() != null && isProtocolValid(ipmatch.getIpProtocol().toString())) {
+ }
+
+ if (ipmatch != null) {
+ if (ipmatch.getIpProtocol() != null && !(isProtocolValid(ipmatch.getIpProtocol().toString()))) {
logger.error("Protocol is not valid");
return false;
}
- } else if (vlanmatch != null) {
- if (vlanmatch.getVlanId() != null && isVlanIdValid(vlanmatch.getVlanId().toString())) {
+
+ }
+
+ if (vlanmatch != null) {
+ if (vlanmatch.getVlanId() != null
+ && !(isVlanIdValid(vlanmatch.getVlanId().getVlanId().getValue().toString()))) {
logger.error("Vlan ID is not in the range 0 - 4095");
return false;
}
- if (vlanmatch.getVlanPcp() != null && isVlanPriorityValid(vlanmatch.getVlanPcp().toString())) {
+ if (vlanmatch.getVlanPcp() != null
+ && !(isVlanPriorityValid(vlanmatch.getVlanPcp().getValue().toString()))) {
logger.error("Vlan priority is not in the range 0 - 7");
return false;
}
}
+
}
return true;
+
}
public static boolean validateActions(List<Action> actions) {
return false;
}
if (outputnodeconnector != null) {
- // TODO
+ if (!outputnodeconnector.getValue().equals(NodeConnectorIDType.ALL)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.CONTROLLER)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.HWPATH)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.ONEPK)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.ONEPK2OPENFLOW)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.ONEPK2PCEP)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.OPENFLOW)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.OPENFLOW2ONEPK)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.OPENFLOW2PCEP)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PCEP)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PCEP2ONEPK)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PCEP2OPENFLOW)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PRODUCTION)
+ || !outputnodeconnector.getValue().equals(NodeConnectorIDType.SWSTACK)) {
+ logger.error("Output Action: NodeConnector Type is not valid");
+ return false;
+ }
+
}
} else if (action instanceof PushMplsAction) {
Integer ethertype = ((PushMplsAction) action).getEthernetType();
logger.error("Ether Type is not valid for PushVlanAction");
return false;
}
- } else if (action instanceof SetDlDstAction || action instanceof SetDlSrcAction) {
+ } else if (action instanceof SetDlDstAction) {
MacAddress address = ((SetDlDstAction) action).getAddress();
if (address != null && !isL2AddressValid(address.toString())) {
logger.error("SetDlDstAction: Address not valid");
}
} else if (action instanceof SetVlanIdAction) {
VlanId vlanid = ((SetVlanIdAction) action).getVlanId();
- if (vlanid != null && !isVlanIdValid(vlanid.toString())) {
- logger.error("Vlan ID %s is not in the range 0 - 4095");
+ if (vlanid != null && !isVlanIdValid(vlanid.getValue().toString())) {
+ logger.error("Vlan ID is not in the range 0 - 4095");
return false;
}
} else if (action instanceof SetVlanPcpAction) {
VlanPcp vlanpcp = ((SetVlanPcpAction) action).getVlanPcp();
- if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.toString())) {
- logger.error("Vlan priority %s is not in the range 0 - 7");
+ if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.getValue().toString())) {
+ logger.error("Vlan priority is not in the range 0 - 7");
return false;
}
}
}
return true;
+
}
public static boolean validateInstructions(Flow flow) {
List<Instruction> instructionsList = new ArrayList<>();
Instructions instructions = flow.getInstructions();
- if( instructions == null ) {
+ if (instructions == null) {
return false;
}
instructionsList = instructions.getInstruction();
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
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.UpdatedFlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
public class FlowConsumerImpl implements IForwardingRulesManager {
protected static final Logger logger = LoggerFactory.getLogger(FlowConsumerImpl.class);
- private final FlowEventListener flowEventListener = new FlowEventListener();
+ // private final FlowEventListener flowEventListener = new
+ // FlowEventListener();
private Registration<NotificationListener> listener1Reg;
private SalFlowService flowService;
// private FlowDataListener listener;
if (null == flowService) {
logger.error("Consumer SAL Service is down or NULL. FRM may not function as intended");
- System.out.println("Consumer SAL Service is down or NULL.");
return;
}
// }
// For switch events
- listener1Reg = FRMConsumerImpl.getNotificationService().registerNotificationListener(flowEventListener);
+ // listener1Reg =
+ // FRMConsumerImpl.getNotificationService().registerNotificationListener(flowEventListener);
if (null == listener1Reg) {
logger.error("Listener to listen on flow data modifcation events");
- System.out.println("Consumer SAL Service is down or NULL.");
return;
}
// addFlowTest();
- System.out.println("-------------------------------------------------------------------");
commitHandler = new FlowDataCommitHandler();
FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(
AddFlowInput firstMsg = input1.build();
if (null != flowService) {
- System.out.println(flowService.toString());
- } else {
- System.out.println("ConsumerFlowService is NULL");
+ logger.error("ConsumerFlowService is NULL");
}
@SuppressWarnings("unused")
Future<RpcResult<AddFlowOutput>> result1 = flowService.addFlow(firstMsg);
private void addFlow(InstanceIdentifier<?> path, Flow dataObject) {
AddFlowInputBuilder input = new AddFlowInputBuilder();
-
- List<Instruction> inst = (dataObject).getInstructions().getInstruction();
+
input.setNode((dataObject).getNode());
input.setPriority((dataObject).getPriority());
input.setMatch((dataObject).getMatch());
input.setCookie((dataObject).getCookie());
input.setInstructions((dataObject).getInstructions());
- dataObject.getMatch().getLayer3Match();
- for (int i = 0; i < inst.size(); i++) {
- System.out.println("i = " + i + inst.get(i).getInstruction().toString());
- System.out.println("i = " + i + inst.get(i).toString());
- }
-
- System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
+ input.setBufferId(dataObject.getBufferId());
+ input.setTableId(dataObject.getTableId());
+ input.setOutPort(dataObject.getOutPort());
+ input.setOutGroup(dataObject.getOutGroup());
+ input.setIdleTimeout(dataObject.getIdleTimeout());
+ input.setHardTimeout(dataObject.getHardTimeout());
+ input.setFlowName(dataObject.getFlowName());
+ input.setFlags(dataObject.getFlags());
+ input.setCookieMask(dataObject.getCookieMask());
+ input.setContainerName(dataObject.getContainerName());
+ input.setBarrier(dataObject.isBarrier());
+ input.setInstallHw(dataObject.isInstallHw());
+ input.setStrict(dataObject.isStrict());
// updating the staticflow cache
/*
- * Commented out... as in many other places... use of ClusteringServices is breaking things
- * insufficient time to debug
- Integer ordinal = staticFlowsOrdinal.get(0);
- staticFlowsOrdinal.put(0, ++ordinal);
- staticFlows.put(ordinal, dataObject);
- */
+ * Commented out... as in many other places... use of ClusteringServices
+ * is breaking things insufficient time to debug Integer ordinal =
+ * staticFlowsOrdinal.get(0); staticFlowsOrdinal.put(0, ++ordinal);
+ * staticFlows.put(ordinal, dataObject);
+ */
// We send flow to the sounthbound plugin
+
flowService.addFlow(input.build());
+
/*
- * Commented out as this will also break due to improper use of ClusteringServices
- updateLocalDatabase((NodeFlow) dataObject, true);
- */
+ * Commented out as this will also break due to improper use of
+ * ClusteringServices updateLocalDatabase((NodeFlow) dataObject, true);
+ */
}
/**
private void removeFlow(InstanceIdentifier<?> path, Flow dataObject) {
RemoveFlowInputBuilder input = new RemoveFlowInputBuilder();
- List<Instruction> inst = (dataObject).getInstructions().getInstruction();
input.setNode((dataObject).getNode());
input.setPriority((dataObject).getPriority());
input.setMatch((dataObject).getMatch());
input.setCookie((dataObject).getCookie());
input.setInstructions((dataObject).getInstructions());
- dataObject.getMatch().getLayer3Match();
- for (int i = 0; i < inst.size(); i++) {
- System.out.println("i = " + i + inst.get(i).getInstruction().toString());
- System.out.println("i = " + i + inst.get(i).toString());
- }
-
- System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
-
+ input.setBufferId(dataObject.getBufferId());
+ input.setTableId(dataObject.getTableId());
+ input.setOutPort(dataObject.getOutPort());
+ input.setOutGroup(dataObject.getOutGroup());
+ input.setIdleTimeout(dataObject.getIdleTimeout());
+ input.setHardTimeout(dataObject.getHardTimeout());
+ input.setFlowName(dataObject.getFlowName());
+ input.setFlags(dataObject.getFlags());
+ input.setCookieMask(dataObject.getCookieMask());
+ input.setContainerName(dataObject.getContainerName());
+ input.setBarrier(dataObject.isBarrier());
+ input.setInstallHw(dataObject.isInstallHw());
+ input.setStrict(dataObject.isStrict());
// updating the staticflow cache
/*
- * Commented out due to problems caused by improper use of ClusteringServices
- Integer ordinal = staticFlowsOrdinal.get(0);
- staticFlowsOrdinal.put(0, ++ordinal);
- staticFlows.put(ordinal, dataObject);
- */
+ * Commented out due to problems caused by improper use of
+ * ClusteringServices Integer ordinal = staticFlowsOrdinal.get(0);
+ * staticFlowsOrdinal.put(0, ++ordinal); staticFlows.put(ordinal,
+ * dataObject);
+ */
// We send flow to the sounthbound plugin
flowService.removeFlow(input.build());
+
/*
- * Commented out due to problems caused by improper use of ClusteringServices
- updateLocalDatabase((NodeFlow) dataObject, false);
- */
+ * Commented out due to problems caused by improper use of
+ * ClusteringServices updateLocalDatabase((NodeFlow) dataObject, false);
+ */
}
/**
// updating the staticflow cache
/*
- * Commented out due to problems caused by improper use of ClusteringServices.
- Integer ordinal = staticFlowsOrdinal.get(0);
- staticFlowsOrdinal.put(0, ++ordinal);
- staticFlows.put(ordinal, dataObject);
- */
+ * Commented out due to problems caused by improper use of
+ * ClusteringServices. Integer ordinal = staticFlowsOrdinal.get(0);
+ * staticFlowsOrdinal.put(0, ++ordinal); staticFlows.put(ordinal,
+ * dataObject);
+ */
// We send flow to the sounthbound plugin
flowService.updateFlow(input.build());
+
/*
- * Commented out due to problems caused by improper use of ClusteringServices.
- updateLocalDatabase((NodeFlow) dataObject, true);
- */
+ * Commented out due to problems caused by improper use of
+ * ClusteringServices. updateLocalDatabase((NodeFlow) dataObject, true);
+ */
}
@SuppressWarnings("unchecked")
private void commitToPlugin(internalTransaction transaction) {
- Set<Entry<InstanceIdentifier<?>, DataObject>> createdEntries = transaction.getModification().getCreatedConfigurationData().entrySet();
+ Set<Entry<InstanceIdentifier<?>, DataObject>> createdEntries = transaction.getModification()
+ .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.
+ * 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.
*/
Set<Entry<InstanceIdentifier<?>, DataObject>> updatedEntries = new HashSet<Entry<InstanceIdentifier<?>, DataObject>>();
updatedEntries.addAll(transaction.getModification().getUpdatedConfigurationData().entrySet());
updatedEntries.removeAll(createdEntries);
- Set<InstanceIdentifier<?>> removeEntriesInstanceIdentifiers = transaction.getModification().getRemovedConfigurationData();
+ Set<InstanceIdentifier<?>> removeEntriesInstanceIdentifiers = transaction.getModification()
+ .getRemovedConfigurationData();
transaction.getModification().getOriginalConfigurationData();
for (Entry<InstanceIdentifier<?>, DataObject> entry : createdEntries) {
- if(entry.getValue() instanceof Flow) {
- System.out.println("Coming add cc in FlowDatacommitHandler");
+ if (entry.getValue() instanceof Flow) {
+ logger.debug("Coming add cc in FlowDatacommitHandler");
+ Flow flow = (Flow) entry.getValue();
+ boolean status = validate(flow);
+ if (!status) {
+ return;
+ }
addFlow(entry.getKey(), (Flow) entry.getValue());
}
}
for (@SuppressWarnings("unused")
Entry<InstanceIdentifier<?>, DataObject> entry : updatedEntries) {
- if(entry.getValue() instanceof Flow) {
- System.out.println("Coming update cc in FlowDatacommitHandler");
+ if (entry.getValue() instanceof Flow) {
+ logger.debug("Coming update cc in FlowDatacommitHandler");
+ Flow flow = (Flow) entry.getValue();
+ boolean status = validate(flow);
+ if (!status) {
+ return;
+ }
updateFlow(entry.getKey(), (Flow) entry.getValue());
}
}
- for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers ) {
+ for (InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers) {
DataObject removeValue = transaction.getModification().getOriginalConfigurationData().get(instanceId);
- if(removeValue instanceof Flow) {
- System.out.println("Coming remove cc in FlowDatacommitHandler");
+ if (removeValue instanceof Flow) {
+ logger.debug("Coming remove cc in FlowDatacommitHandler");
+ Flow flow = (Flow) removeValue;
+ boolean status = validate(flow);
+ if (!status) {
+ return;
+ }
removeFlow(instanceId, (Flow) removeValue);
}
@Override
public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
// We should verify transaction
- System.out.println("Coming in FlowDatacommitHandler");
+ logger.debug("Coming in FlowDatacommitHandler");
internalTransaction transaction = new internalTransaction(modification);
transaction.prepareUpdate();
return transaction;
Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
-
- // validating the DataObject
- DataObject value = entry.getValue();
- if(value instanceof Flow ) {
- Flow flow = (Flow)value;
- boolean status = validate(flow);
- if (!status) {
- return;
- }
- // Presence check
- /*
- * This is breaking due to some improper use of caches...
- *
- if (flowEntryExists(flow)) {
- String error = "Entry with this name on specified table already exists";
- logger.warn("Entry with this name on specified table already exists: {}", entry);
- logger.error(error);
- return;
- }
- if (originalSwView.containsKey(entry)) {
- logger.warn("Operation Rejected: A flow with same match and priority exists on the target node");
- logger.trace("Aborting to install {}", entry);
- continue;
- }
- */
- if (!FRMUtil.validateMatch(flow)) {
- logger.error("Not a valid Match");
- return;
- }
- if (!FRMUtil.validateInstructions(flow)) {
- logger.error("Not a valid Instruction");
- return;
- }
- /*
- * Commented out due to Clustering Services issues
- * preparePutEntry(entry.getKey(), flow);
- */
- }
}
// removals = modification.getRemovedConfigurationData();
Flow original = originalSwView.get(key);
if (original != null) {
// It is update for us
- System.out.println("Coming update in FlowDatacommitHandler");
updates.put(key, flow);
} else {
// It is addition for us
- System.out.println("Coming add in FlowDatacommitHandler");
additions.put(key, flow);
}
}
commitToPlugin(this);
// We return true if internal transaction is successful.
// return Rpcs.getRpcResult(true, null, Collections.emptySet());
- return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
+ return Rpcs.getRpcResult(true, null, Collections.<RpcError> emptySet());
}
/**
// NOOP - we did not modified any internal state during
// requestCommit phase
// return Rpcs.getRpcResult(true, null, Collections.emptySet());
- return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
+ return Rpcs.getRpcResult(true, null, Collections.<RpcError> emptySet());
}
- public boolean validate(Flow flow) {
-
- String msg = ""; // Specific part of warn/error log
-
- boolean result = true;
- // flow Name validation
- if (flow.getFlowName() == null || flow.getFlowName().trim().isEmpty()
- || !flow.getFlowName().matches(NAMEREGEX)) {
- msg = "Invalid Flow name";
- result = false;
- }
- // Node Validation
- if (result == true && flow.getNode() == null) {
- msg = "Node is null";
- result = false;
- }
-
- // TODO: Validate we are seeking to program a flow against a valid Node
-
- if (result == true && flow.getPriority() != null) {
- if (flow.getPriority() < 0 || flow.getPriority() > 65535) {
- msg = String.format("priority %s is not in the range 0 - 65535",
- flow.getPriority());
- result = false;
- }
- }
- if (result == false) {
- logger.warn("Invalid Configuration for flow {}. The failure is {}",flow,msg);
- logger.error("Invalid Configuration ({})",msg);
- }
- return result;
- }
-
private boolean flowEntryExists(Flow flow) {
// Flow name has to be unique on per table id basis
for (ConcurrentMap.Entry<FlowKey, Flow> entry : originalSwView.entrySet()) {
}
}
- final class FlowEventListener implements SalFlowListener {
-
- List<FlowAdded> addedFlows = new ArrayList<>();
- List<FlowRemoved> removedFlows = new ArrayList<>();
- List<FlowUpdated> updatedFlows = new ArrayList<>();
-
- @Override
- public void onFlowAdded(FlowAdded notification) {
- System.out.println("added flow..........................");
- addedFlows.add(notification);
- }
-
- @Override
- public void onFlowRemoved(FlowRemoved notification) {
- removedFlows.add(notification);
- };
-
- @Override
- public void onFlowUpdated(FlowUpdated notification) {
- updatedFlows.add(notification);
- }
-
- @Override
- public void onSwitchFlowRemoved(SwitchFlowRemoved notification) {
- // TODO
- }
-
- @Override
- public void onNodeErrorNotification(NodeErrorNotification notification) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onNodeExperimenterErrorNotification(NodeExperimenterErrorNotification notification) {
- // TODO Auto-generated method stub
-
- };
-
- }
-
// Commented out DataChangeListene - to be used by Stats
// final class FlowDataListener implements DataChangeListener {
// }
// }
+ public boolean validate(Flow flow) {
+
+ String msg = ""; // Specific part of warn/error log
+
+ boolean result = true;
+ // flow Name validation
+ if (flow.getFlowName() == null || flow.getFlowName().trim().isEmpty() || !flow.getFlowName().matches(NAMEREGEX)) {
+ msg = "Invalid Flow name";
+ result = false;
+ }
+ // Node Validation
+ if (result == true && flow.getNode() == null) {
+ msg = "Node is null";
+ result = false;
+ }
+
+ // TODO: Validate we are seeking to program a flow against a valid
+ // Node
+
+ if (result == true && flow.getPriority() != null) {
+ if (flow.getPriority() < 0 || flow.getPriority() > 65535) {
+ msg = String.format("priority %s is not in the range 0 - 65535", flow.getPriority());
+ result = false;
+ }
+ }
+
+ // Presence check
+ /*
+ * This is breaking due to some improper use of caches...
+ *
+ * if (flowEntryExists(flow)) { String error =
+ * "Entry with this name on specified table already exists";
+ * logger.warn(
+ * "Entry with this name on specified table already exists: {}" ,
+ * entry); logger.error(error); return; } if
+ * (originalSwView.containsKey(entry)) { logger.warn(
+ * "Operation Rejected: A flow with same match and priority exists on the target node"
+ * ); logger.trace("Aborting to install {}", entry); continue; }
+ */
+ if (!FRMUtil.validateMatch(flow)) {
+ logger.error("Not a valid Match");
+ result = false;
+ }
+ if (!FRMUtil.validateInstructions(flow)) {
+ logger.error("Not a valid Instruction");
+ result = false;
+ }
+ if (result == false) {
+ logger.warn("Invalid Configuration for flow {}. The failure is {}", flow, msg);
+ logger.error("Invalid Configuration ({})", msg);
+ }
+ return result;
+ }
+
private static void updateLocalDatabase(NodeFlow entry, boolean add) {
updateSwViewes(entry, add);
private final GroupEventListener groupEventListener = new GroupEventListener();
private Registration<NotificationListener> groupListener;
private SalGroupService groupService;
- private GroupDataCommitHandler commitHandler;
+ private GroupDataCommitHandler groupCommitHandler;
private ConcurrentMap<GroupKey, Group> originalSwGroupView;
private ConcurrentMap<GroupKey, Group> installedSwGroupView;
InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Groups.class).toInstance();
groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
- clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
- container = FRMConsumerImpl.getContainer();
-
if (!(cacheStartup())) {
logger.error("Unanle to allocate/retrieve group cache");
System.out.println("Unable to allocate/retrieve group cache");
return;
}
- commitHandler = new GroupDataCommitHandler();
- FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
+ groupCommitHandler = new GroupDataCommitHandler();
+ FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, groupCommitHandler);
+ clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
+ container = FRMConsumerImpl.getContainer();
}
private boolean allocateGroupCaches() {
logger.error("Container Name is invalid %s" + containerName);
return new Status(StatusCode.BADREQUEST, "Container Name is invalid");
}
-
+
groupName = group.getGroupName();
if (!FRMUtil.isNameValid(groupName)) {
logger.error("Group Name is invalid %s" + groupName);
return new Status(StatusCode.BADREQUEST, "Group Name is invalid");
}
-
- /* returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName);
-
- if (FRMUtil.operation.ADD == operation && returnResult) {
- logger.error("Record with same Group Name exists");
- return new Status(StatusCode.BADREQUEST, "Group record exists");
- } else if (!returnResult) {
- logger.error("Group record does not exist");
- return new Status(StatusCode.BADREQUEST, "Group record does not exist");
- }*/
-
+
if (!(group.getGroupType().getIntValue() >= GroupTypes.GroupAll.getIntValue() && group.getGroupType()
.getIntValue() <= GroupTypes.GroupFf.getIntValue())) {
logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
}
return new Status(StatusCode.SUCCESS);
-
}
- /* private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) {
- if (!originalSwGroupView.containsKey(key)) {
- return false;
- }
-
- for (ConcurrentMap.Entry<GroupKey, Group> entry : originalSwGroupView.entrySet()) {
- if (entry.getValue().getGroupName().equals(groupName)) {
- if (entry.getValue().getContainerName().equals(containerName)) {
- return true;
- }
- }
- }
- return true;
- }*/
-
/**
* Update Group entries to the southbound plugin/inventory and our internal
* database
logger.error("Group data object validation failed %s" + groupUpdateDataObject.getGroupName());
return groupOperationStatus;
}
-
- /*if (originalSwGroupView.containsKey(groupKey)) {
- originalSwGroupView.remove(groupKey);
- originalSwGroupView.put(groupKey, groupUpdateDataObject);
- }
-*/
- if (groupUpdateDataObject.isInstall()) {
- UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
- updateGroupBuilder = new UpdatedGroupBuilder();
- updateGroupBuilder.fieldsFrom(groupUpdateDataObject);
- groupData.setUpdatedGroup(updateGroupBuilder.build());
- // TODO how to get original group and modified group.
-
- /* if (installedSwGroupView.containsKey(groupKey)) {
- installedSwGroupView.remove(groupKey);
- installedSwGroupView.put(groupKey, groupUpdateDataObject);
- }*/
-
- groupService.updateGroup(groupData.build());
- }
-
+
+ UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
+ updateGroupBuilder = new UpdatedGroupBuilder();
+ updateGroupBuilder.fieldsFrom(groupUpdateDataObject);
+ groupData.setUpdatedGroup(updateGroupBuilder.build());
+ groupService.updateGroup(groupData.build());
return groupOperationStatus;
}
logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName());
return groupOperationStatus;
}
-
- //originalSwGroupView.put(groupKey, groupAddDataObject);
-
- if (groupAddDataObject.isInstall()) {
- AddGroupInputBuilder groupData = new AddGroupInputBuilder();
- groupData.setBuckets(groupAddDataObject.getBuckets());
- groupData.setContainerName(groupAddDataObject.getContainerName());
- groupData.setGroupId(groupAddDataObject.getGroupId());
- groupData.setGroupType(groupAddDataObject.getGroupType());
- groupData.setNode(groupAddDataObject.getNode());
- // installedSwGroupView.put(groupKey, groupAddDataObject);
- groupService.addGroup(groupData.build());
- }
-
+
+ AddGroupInputBuilder groupData = new AddGroupInputBuilder();
+ groupData.setBuckets(groupAddDataObject.getBuckets());
+ groupData.setContainerName(groupAddDataObject.getContainerName());
+ groupData.setGroupId(groupAddDataObject.getGroupId());
+ groupData.setGroupType(groupAddDataObject.getGroupType());
+ groupData.setNode(groupAddDataObject.getNode());
+ groupService.addGroup(groupData.build());
return groupOperationStatus;
}
logger.error("Group data object validation failed %s" + groupRemoveDataObject.getGroupName());
return groupOperationStatus;
}
- //originalSwGroupView.put(groupKey, groupAddDataObject);
-
- if (groupRemoveDataObject.isInstall()) {
- RemoveGroupInputBuilder groupData = new RemoveGroupInputBuilder();
- groupData.setBuckets(groupRemoveDataObject.getBuckets());
- groupData.setContainerName(groupRemoveDataObject.getContainerName());
- groupData.setGroupId(groupRemoveDataObject.getGroupId());
- groupData.setGroupType(groupRemoveDataObject.getGroupType());
- groupData.setNode(groupRemoveDataObject.getNode());
- // installedSwGroupView.put(groupKey, groupAddDataObject);
- groupService.removeGroup(groupData.build());
- }
-
+
+ RemoveGroupInputBuilder groupData = new RemoveGroupInputBuilder();
+ groupData.setBuckets(groupRemoveDataObject.getBuckets());
+ groupData.setContainerName(groupRemoveDataObject.getContainerName());
+ groupData.setGroupId(groupRemoveDataObject.getGroupId());
+ groupData.setGroupType(groupRemoveDataObject.getGroupType());
+ groupData.setNode(groupRemoveDataObject.getNode());
+ groupService.removeGroup(groupData.build());
return groupOperationStatus;
}
}
}
- return Rpcs.getRpcResult(true, null, null);
+ return Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
}
private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
@Override
public void onGroupAdded(GroupAdded notification) {
- System.out.println("added Group..........................");
addedGroups.add(notification);
}
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.UpdatedMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.BandType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Drop;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DscpRemark;
private ConcurrentMap<MeterKey, Meter> inactiveMeters;
@SuppressWarnings("unused")
private IContainer container;
-
- private IClusterContainerServices clusterMeterContainerService = null;
-
+ private IClusterContainerServices clusterMeterContainerService = null;
public MeterConsumerImpl() {
InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(Meters.class).toInstance();
meterService = FRMConsumerImpl.getProviderSession().getRpcService(SalMeterService.class);
clusterMeterContainerService = FRMConsumerImpl.getClusterContainerService();
-
container = FRMConsumerImpl.getContainer();
if (!(cacheStartup())) {
*/
private Status addMeter(InstanceIdentifier<?> path, Meter meterAddDataObject) {
MeterKey meterKey = meterAddDataObject.getKey();
-
- if (null != meterKey && validateMeter(meterAddDataObject, FRMUtil.operation.ADD).isSuccess()) {
- if (meterAddDataObject.isInstall()) {
- AddMeterInputBuilder meterBuilder = new AddMeterInputBuilder();
-
- meterBuilder.setContainerName(meterAddDataObject.getContainerName());
- meterBuilder.setFlags(meterAddDataObject.getFlags());
- meterBuilder.setMeterBandHeaders(meterAddDataObject.getMeterBandHeaders());
- meterBuilder.setMeterId(meterAddDataObject.getMeterId());
- meterBuilder.setNode(meterAddDataObject.getNode());
- // originalSwMeterView.put(meterKey, meterAddDataObject);
- meterService.addMeter(meterBuilder.build());
- }
-
- // originalSwMeterView.put(meterKey, meterAddDataObject);
- } else {
+
+ if (null != meterKey && validateMeter(meterAddDataObject, FRMUtil.operation.ADD).isSuccess()) {
+ AddMeterInputBuilder meterBuilder = new AddMeterInputBuilder();
+ meterBuilder.setContainerName(meterAddDataObject.getContainerName());
+ meterBuilder.setFlags(meterAddDataObject.getFlags());
+ meterBuilder.setMeterBandHeaders(meterAddDataObject.getMeterBandHeaders());
+ meterBuilder.setMeterId(new MeterId(meterAddDataObject.getId()));
+ meterBuilder.setNode(meterAddDataObject.getNode());
+ meterService.addMeter(meterBuilder.build());
+ } else {
return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
}
private Status updateMeter(InstanceIdentifier<?> path, Meter meterUpdateDataObject) {
MeterKey meterKey = meterUpdateDataObject.getKey();
UpdatedMeterBuilder updateMeterBuilder = null;
-
- if (null != meterKey && validateMeter(meterUpdateDataObject, FRMUtil.operation.UPDATE).isSuccess()) {
-
- /* if (originalSwMeterView.containsKey(meterKey)) {
- originalSwMeterView.remove(meterKey);
- originalSwMeterView.put(meterKey, meterUpdateDataObject);
- }*/
-
- if (meterUpdateDataObject.isInstall()) {
- UpdateMeterInputBuilder updateMeterInputBuilder = new UpdateMeterInputBuilder();
- updateMeterBuilder = new UpdatedMeterBuilder();
- updateMeterBuilder.fieldsFrom(meterUpdateDataObject);
- updateMeterInputBuilder.setUpdatedMeter(updateMeterBuilder.build());
-
- /* if (installedSwMeterView.containsKey(meterKey)) {
- installedSwMeterView.remove(meterKey);
- installedSwMeterView.put(meterKey, meterUpdateDataObject);
- }*/
-
- meterService.updateMeter(updateMeterInputBuilder.build());
- }
-
+
+ if (null != meterKey && validateMeter(meterUpdateDataObject, FRMUtil.operation.UPDATE).isSuccess()) { UpdateMeterInputBuilder updateMeterInputBuilder = new UpdateMeterInputBuilder();
+ updateMeterBuilder = new UpdatedMeterBuilder();
+ updateMeterBuilder.fieldsFrom(meterUpdateDataObject);
+ updateMeterInputBuilder.setUpdatedMeter(updateMeterBuilder.build());
+ meterService.updateMeter(updateMeterInputBuilder.build());
} else {
return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
}
private Status removeMeter(InstanceIdentifier<?> path, Meter meterRemoveDataObject) {
MeterKey meterKey = meterRemoveDataObject.getKey();
- if (null != meterKey && validateMeter(meterRemoveDataObject, FRMUtil.operation.DELETE).isSuccess()) {
- if (meterRemoveDataObject.isInstall()) {
- RemoveMeterInputBuilder meterBuilder = new RemoveMeterInputBuilder();
- meterBuilder.setContainerName(meterRemoveDataObject.getContainerName());
- meterBuilder.setNode(meterRemoveDataObject.getNode());
- meterBuilder.setFlags(meterRemoveDataObject.getFlags());
- meterBuilder.setMeterBandHeaders(meterRemoveDataObject.getMeterBandHeaders());
- meterBuilder.setMeterId(meterRemoveDataObject.getMeterId());
- meterBuilder.setNode(meterRemoveDataObject.getNode());
- // originalSwMeterView.put(meterKey, meterAddDataObject);
- meterService.removeMeter(meterBuilder.build());
- }
-
- // originalSwMeterView.put(meterKey, meterAddDataObject);
+ if (null != meterKey && validateMeter(meterRemoveDataObject, FRMUtil.operation.DELETE).isSuccess()) {
+ RemoveMeterInputBuilder meterBuilder = new RemoveMeterInputBuilder();
+ meterBuilder.setContainerName(meterRemoveDataObject.getContainerName());
+ meterBuilder.setNode(meterRemoveDataObject.getNode());
+ meterBuilder.setFlags(meterRemoveDataObject.getFlags());
+ meterBuilder.setMeterBandHeaders(meterRemoveDataObject.getMeterBandHeaders());
+ meterBuilder.setMeterId(meterRemoveDataObject.getMeterId());
+ meterBuilder.setNode(meterRemoveDataObject.getNode());
+ meterService.removeMeter(meterBuilder.build());
} else {
return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
}
return returnStatus;
}
- /* returnResult = doesMeterEntryExists(meter.getKey(), meterName, containerName);
-
- if (FRMUtil.operation.ADD == operation && returnResult) {
- logger.error("Record with same Meter Name exists");
- returnStatus = new Status(StatusCode.BADREQUEST, "Meter record exists");
- return returnStatus;
- } else if (!returnResult) {
- logger.error("Group record does not exist");
- returnStatus = new Status(StatusCode.BADREQUEST, "Meter record does not exist");
- return returnStatus;
- }*/
-
for (int i = 0; i < meter.getMeterBandHeaders().getMeterBandHeader().size(); i++) {
if (!meter.getFlags().isMeterBurst()) {
if (0 < meter.getMeterBandHeaders().getMeterBandHeader().get(i).getBurstSize()) {
return new Status(StatusCode.SUCCESS);
}
- /*private boolean doesMeterEntryExists(MeterKey key, String meterName, String containerName) {
- if (!originalSwMeterView.containsKey(key)) {
- return false;
- }
-
- for (Entry<MeterKey, Meter> entry : originalSwMeterView.entrySet()) {
- if (entry.getValue().getMeterName().equals(meterName)) {
- if (entry.getValue().getContainerName().equals(containerName)) {
- return true;
- }
- }
- }
- return false;
- }*/
-
- private final class InternalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
+ final class InternalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
private final DataModification<InstanceIdentifier<?>, DataObject> modification;
public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<?>, DataObject> requestCommit(
DataModification<InstanceIdentifier<?>, DataObject> modification) {
// We should verify transaction
- System.out.println("Coming in MeterDataCommitHandler");
InternalTransaction transaction = new InternalTransaction(modification);
transaction.prepareUpdate();
return transaction;
}
}
}
+
return null;
}
}
</generator>
<generator>
<codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
- <outputBaseDir>target/site/restconf</outputBaseDir>
+ <outputBaseDir>target/site/models</outputBaseDir>
</generator>
</codeGenerators>
<inspectDependencies>true</inspectDependencies>
</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>
<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>
import java.util.concurrent.Callable
import java.util.WeakHashMap
import javax.annotation.concurrent.GuardedBy
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry
-class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable {
+class BindingAwareBrokerImpl implements BindingAwareBroker, RpcProviderRegistry, AutoCloseable {
private static val log = LoggerFactory.getLogger(BindingAwareBrokerImpl)
private InstanceIdentifier<? extends DataObject> root = InstanceIdentifier.builder().toInstance();
* Registers RPC Implementation
*
*/
- def <T extends RpcService> registerRpcImplementation(Class<T> type, T service, OsgiProviderContext context,
- Hashtable<String, String> properties) {
+ override <T extends RpcService> addRpcImplementation(Class<T> type, T service) {
+ checkNotNull(type, "Service type should not be null")
+ checkNotNull(service, "Service type should not be null")
+
val proxy = getManagedDirectProxy(type)
checkState(proxy.delegate === null, "The Service for type %s is already registered", type)
- val osgiReg = context.bundleContext.registerService(type, service, properties);
proxy.delegate = service;
- return new RpcServiceRegistrationImpl<T>(type, service, osgiReg, this);
+ return new RpcServiceRegistrationImpl<T>(type, service, this);
}
- def <T extends RpcService> RoutedRpcRegistration<T> registerRoutedRpcImplementation(Class<T> type, T service,
- OsgiProviderContext context) {
+ override <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type, T service) {
+ checkNotNull(type, "Service type should not be null")
+ checkNotNull(service, "Service type should not be null")
+
val router = resolveRpcRouter(type);
checkState(router !== null)
return new RoutedRpcRegistrationImpl<T>(service, router, this)
}
+
+ override <T extends RpcService> getRpcService(Class<T> service) {
+ checkNotNull(service, "Service should not be null");
+ return getManagedDirectProxy(service) as T;
+ }
private def <T extends RpcService> RpcRouter<T> resolveRpcRouter(Class<T> type) {
class RpcServiceRegistrationImpl<T extends RpcService> extends AbstractObjectRegistration<T> implements RpcRegistration<T> {
- val ServiceRegistration<T> osgiRegistration;
private var BindingAwareBrokerImpl broker;
@Property
val Class<T> serviceType;
- public new(Class<T> type, T service, ServiceRegistration<T> osgiReg, BindingAwareBrokerImpl broker) {
+ public new(Class<T> type, T service, BindingAwareBrokerImpl broker) {
super(service);
this._serviceType = type;
- this.osgiRegistration = osgiReg;
this.broker = broker;
}
}
override <T extends RpcService> addRpcImplementation(Class<T> type, T implementation) {
-
- // TODO Auto-generated method stub
- val properties = new Hashtable<String, String>();
- properties.salServiceType = SAL_SERVICE_TYPE_PROVIDER
-
- // Fill requirements
- val salReg = broker.registerRpcImplementation(type, implementation, this, properties)
+ val salReg = broker.addRpcImplementation(type, implementation)
registeredServices.put(type, salReg)
return salReg;
}
override <T extends RpcService> addRoutedRpcImplementation(Class<T> type, T implementation) throws IllegalStateException {
- checkNotNull(type, "Service type should not be null")
- checkNotNull(implementation, "Service type should not be null")
-
- val salReg = broker.registerRoutedRpcImplementation(type, implementation, this)
+ val salReg = broker.addRoutedRpcImplementation(type, implementation)
registeredServices.put(type, salReg)
return salReg;
}
identity binding-broker-impl {
base config:module-type;
config:provided-service sal:binding-broker-osgi-registry;
+ config:provided-service sal:binding-rpc-registry;
config:java-name-prefix BindingBrokerImpl;
}
</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>
<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>
<plugin>
</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>
<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>
<plugin>
</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>
<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>
</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>
<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>
<plugin>
EventLoopGroup bossGroup = getBossThreadGroupDependency();
EventLoopGroup workerGroup = getWorkerThreadGroupDependency();
- Optional<SSLContext> maybeContext = Optional.absent();
NetconfClientDispatcher dispatcher = null;
if(getTcpOnly()) {
- dispatcher = new NetconfClientDispatcher(maybeContext , bossGroup, workerGroup);
+ dispatcher = new NetconfClientDispatcher( bossGroup, workerGroup);
} else {
AuthenticationHandler authHandler = new LoginPassword(getUsername(),getPassword());
dispatcher = new NetconfSshClientDispatcher(authHandler , bossGroup, workerGroup);
<version>2.4</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-model-util</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
</dependencies>
<build>
import javax.activation.UnsupportedDataTypeException;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.*;
import org.opendaylight.yangtools.yang.model.api.*;
import org.opendaylight.yangtools.yang.model.api.type.*;
List<SimpleNode<?>> nodeLeafLists = nodeParent.getSimpleNodesByName(node.getNodeType());
for (SimpleNode<?> nodeLeafList : nodeLeafLists) {
- writeValueOfNodeByType(writer, nodeLeafList, schema.getType());
+ writeValueOfNodeByType(writer, nodeLeafList, schema.getType(), schema);
}
-
writer.endArray();
}
private void writeLeaf(JsonWriter writer, SimpleNode<?> node, LeafSchemaNode schema) throws IOException {
writeName(node, schema, writer);
- writeValueOfNodeByType(writer, node, schema.getType());
+ writeValueOfNodeByType(writer, node, schema.getType(), schema);
}
- private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type)
- throws IOException {
+ private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type,
+ DataSchemaNode schema) throws IOException {
String value = String.valueOf(node.getValue());
- // TODO check Leafref, InstanceIdentifierTypeDefinition,
- // IdentityrefTypeDefinition, UnionTypeDefinition
TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
- if (baseType instanceof InstanceIdentifierTypeDefinition) {
+
+ // TODO check InstanceIdentifierTypeDefinition,
+ // IdentityrefTypeDefinition
+ if (baseType instanceof IdentityrefTypeDefinition) {
+ if (node.getValue() instanceof QName) {
+ QName qName = (QName) node.getValue();
+
+ ControllerContext contContext = ControllerContext.getInstance();
+ String moduleName = contContext.findModuleByNamespace(qName.getNamespace());
+
+ writer.value(moduleName + ":" + qName.getLocalName());
+ }
+
+ } else if (baseType instanceof LeafrefTypeDefinition) {
+ ControllerContext contContext = ControllerContext.getInstance();
+ LeafSchemaNode lfSchemaNode = contContext.resolveTypeFromLeafref((LeafrefTypeDefinition) baseType, schema);
+ if (lfSchemaNode != null) {
+ writeValueOfNodeByType(writer, node, lfSchemaNode.getType(), lfSchemaNode);
+ } else {
+ writer.value(value);
+ }
+ } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
writer.value(((InstanceIdentifierTypeDefinition) baseType).getPathStatement().toString());
} else if (baseType instanceof UnionTypeDefinition) {
processTypeIsUnionType(writer, (UnionTypeDefinition) baseType, value);
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
import org.opendaylight.yangtools.yang.model.api.RpcDefinition
import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
import static com.google.common.base.Preconditions.*
private val BiMap<URI, String> uriToModuleName = HashBiMap.create();
private val Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
- private val Map<QName,RpcDefinition> qnameToRpc = new ConcurrentHashMap();
-
+ private val Map<QName, RpcDefinition> qnameToRpc = new ConcurrentHashMap();
private new() {
if (INSTANCE !== null) {
static def getInstance() {
return INSTANCE
}
-
+
private def void checkPreconditions() {
if (schemas === null) {
throw new ResponseException(Response.Status.SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
private def dispatch CharSequence toRestconfIdentifier(PathArgument argument, DataSchemaNode node) {
throw new IllegalArgumentException("Conversion of generic path argument is not supported");
}
-
+
def findModuleByNamespace(URI namespace) {
checkPreconditions
var module = uriToModuleName.get(namespace)
return str;
}
}
-
+
private def QName toQName(String name) {
val module = name.toModuleName;
val node = name.toNodeName;
val namespace = moduleNameToUri.get(module);
- return new QName(namespace,null,node);
+ return new QName(namespace, null, node);
}
-
+
def getRpcDefinition(String name) {
return qnameToRpc.get(name.toQName)
}
override onGlobalContextUpdated(SchemaContext context) {
this.schemas = context;
- for(operation : context.operations) {
- val qname = new QName(operation.QName.namespace,null,operation.QName.localName);
- qnameToRpc.put(qname,operation);
+ for (operation : context.operations) {
+ val qname = new QName(operation.QName.namespace, null, operation.QName.localName);
+ qnameToRpc.put(qname, operation);
+ }
+ }
+
+ /**
+ * Resolve target type from leafref type.
+ *
+ * According to RFC 6020 referenced element has to be leaf (chapter 9.9).
+ * Therefore if other element is referenced then null value is returned.
+ *
+ * Currently only cases without path-predicate are supported.
+ *
+ * @param leafRef
+ * @param schemaNode
+ * data schema node which contains reference
+ * @return type if leaf is referenced and it is possible to find referenced
+ * node in schema context. In other cases null value is returned
+ */
+ def LeafSchemaNode resolveTypeFromLeafref(LeafrefTypeDefinition leafRef, DataSchemaNode schemaNode) {
+ val xPath = leafRef.getPathStatement();
+ val module = SchemaContextUtil.findParentModule(schemas, schemaNode);
+
+ var SchemaNode foundSchemaNode
+ if (xPath.isAbsolute()) {
+ foundSchemaNode = SchemaContextUtil.findDataSchemaNode(schemas, module, xPath);
+ } else {
+ foundSchemaNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemas, module, schemaNode, xPath);
+ }
+
+ if (foundSchemaNode instanceof LeafSchemaNode) {
+ return foundSchemaNode as LeafSchemaNode;
}
+
+ return null;
}
-
}
null, byteArrayOS);
jsonResult = byteArrayOS.toString();
- try {
- outputToFile(byteArrayOS, outputPath);
- } catch (IOException e) {
- System.out.println("Output file wasn't cloased sucessfuly.");
+ if (outputPath != null) {
+ try {
+ outputToFile(byteArrayOS, outputPath);
+ } catch (IOException e) {
+ System.out.println("Output file wasn't cloased sucessfuly.");
+ }
}
return jsonResult;
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.regex.*;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.*;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+public class ToJsonIdentityrefTest {
+
+ private static Set<Module> modules;
+ private static DataSchemaNode dataSchemaNode;
+
+ @BeforeClass
+ public static void initialization() {
+ modules = TestUtils.resolveModules("/yang-to-json-conversion/identityref");
+ assertEquals(2, modules.size());
+ Module module = TestUtils.resolveModule("identityref-module", modules);
+ assertNotNull(module);
+ dataSchemaNode = TestUtils.resolveDataSchemaNode(module, "cont");
+ assertNotNull(dataSchemaNode);
+
+ }
+
+ @Test
+ public void identityrefToJsonTest() {
+ String json = null;
+ try {
+ json = TestUtils
+ .writeCompNodeWithSchemaContextToJson(prepareCompositeNode(), null, modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ assertNotNull(json);
+ Pattern ptrn = Pattern.compile(".*\"lf1\"\\p{Space}*:\\p{Space}*\"identityref-module:name_test\".*",
+ Pattern.DOTALL);
+ Matcher mtch = ptrn.matcher(json);
+
+ assertTrue(mtch.matches());
+ }
+
+ private CompositeNode prepareCompositeNode() {
+ MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
+ ModifyAction.CREATE, null);
+ MutableSimpleNode<?> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1"), cont,
+ TestUtils.buildQName("name_test", "identityref:module", "2013-12-2"), ModifyAction.CREATE, null);
+ cont.getChildren().add(lf1);
+ cont.init();
+
+ return cont;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.regex.Matcher;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.*;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+public class ToJsonLeafrefType {
+ private static Set<Module> modules;
+ private static DataSchemaNode dataSchemaNode;
+
+ @BeforeClass
+ public static void initialization() {
+ modules = TestUtils.resolveModules("/yang-to-json-conversion/leafref");
+ assertEquals(2, modules.size());
+ Module module = TestUtils.resolveModule("main-module", modules);
+ assertNotNull(module);
+ dataSchemaNode = TestUtils.resolveDataSchemaNode(module, "cont");
+ assertNotNull(dataSchemaNode);
+
+ }
+
+ @Test
+ public void leafrefAbsolutePathToExistingLeafTest() {
+ String json = null;
+ try {
+ json = TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
+ .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_absolut_ref_to_existing_leaf.xml"),
+ "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ assertNotNull(json);
+ java.util.regex.Pattern ptrn = java.util.regex.Pattern.compile(".*\"lf3\":\\p{Blank}*true.*",
+ java.util.regex.Pattern.DOTALL);
+ Matcher mtch = ptrn.matcher(json);
+ assertTrue(mtch.matches());
+ }
+
+ @Test
+ public void leafrefRelativePathToExistingLeafTest() {
+ String json = null;
+ try {
+ json = TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
+ .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_relativ_ref_to_existing_leaf.xml"),
+ "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ assertNotNull(json);
+ java.util.regex.Pattern ptrn = java.util.regex.Pattern.compile(".*\"lf2\":\\p{Blank}*121.*",
+ java.util.regex.Pattern.DOTALL);
+ Matcher mtch = ptrn.matcher(json);
+ assertTrue(mtch.matches());
+ }
+
+ /**
+ * Tests case when reference to not existing element is present. In this
+ * case value from single node is printed as string.
+ */
+ @Test
+ public void leafrefToNonExistingLeafTest() {
+ String json = null;
+ try {
+ json = TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
+ .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_ref_to_non_existing_leaf.xml"),
+ "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ assertNotNull(json);
+ java.util.regex.Pattern ptrn = java.util.regex.Pattern.compile(".*\"lf5\":\\p{Blank}*\"137\".*",
+ java.util.regex.Pattern.DOTALL);
+ Matcher mtch = ptrn.matcher(json);
+ assertTrue(mtch.matches());
+ }
+
+ /**
+ * Tests case when non leaf element is referenced. In this case value from
+ * single node is printed as string.
+ */
+ @Test
+ public void leafrefToNotLeafTest() {
+ String json = null;
+ try {
+ json = TestUtils.writeCompNodeWithSchemaContextToJson(
+ TestUtils.loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_ref_to_not_leaf.xml"),
+ "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ assertNotNull(json);
+ java.util.regex.Pattern ptrn = java.util.regex.Pattern.compile(
+ ".*\"cont-augment-module\\p{Blank}*:\\p{Blank}*lf6\":\\p{Blank}*\"44.33\".*",
+ java.util.regex.Pattern.DOTALL);
+ Matcher mtch = ptrn.matcher(json);
+ assertTrue(mtch.matches());
+ }
+
+ /**
+ * Tests case when leaflist element is refers to leaf.
+ */
+ @Test
+ public void leafrefFromLeafListToLeafTest() {
+ String json = null;
+ try {
+ json = TestUtils
+ .writeCompNodeWithSchemaContextToJson(
+ TestUtils
+ .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_relativ_ref_from_leaflist_to_existing_leaf.xml"),
+ "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ assertNotNull(json);
+ java.util.regex.Pattern ptrn = java.util.regex.Pattern
+ .compile(
+ ".*\"cont-augment-module\\p{Blank}*:\\p{Blank}*lflst1\":\\p{Blank}*.*345,\\p{Space}*346,\\p{Space}*347.*",
+ java.util.regex.Pattern.DOTALL);
+ Matcher mtch = ptrn.matcher(json);
+ assertTrue(mtch.matches());
+ }
+
+ /**
+ * Tests case when leaflist element is refers to leaf.
+ */
+ @Test
+ public void leafrefFromLeafrefToLeafrefTest() {
+ String json = null;
+ try {
+ json = TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
+ .loadCompositeNode("/yang-to-json-conversion/leafref/xml/data_from_leafref_to_leafref.xml"),
+ "/yang-to-json-conversion/leafref/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ assertNotNull(json);
+ java.util.regex.Pattern ptrn = java.util.regex.Pattern.compile(
+ ".*\"cont-augment-module\\p{Blank}*:\\p{Blank}*lf7\":\\p{Blank}*200.*", java.util.regex.Pattern.DOTALL);
+ Matcher mtch = ptrn.matcher(json);
+ assertTrue(mtch.matches());
+ }
+
+}
--- /dev/null
+module identity-module {
+ namespace "identity:module";
+
+ prefix "idemod";
+ revision 2013-12-2 {
+ }
+
+ identity iden {
+ }
+}
\ No newline at end of file
--- /dev/null
+module identityref-module {
+ namespace "identityref:module";
+
+ prefix "iderefmod";
+
+ import identity-module {prefix idemo; revision-date 2013-12-2;}
+
+ revision 2013-12-2 {
+ }
+
+ container cont {
+ leaf lf1 {
+ type identityref {
+ base "idemo:iden";
+ }
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+module cont-augment-module {
+ namespace "cont:augment:module";
+
+ prefix "cntaugmod";
+
+ import main-module {prefix mamo; revision-date 2013-12-2;}
+
+ revision 2013-12-2 {
+
+ }
+
+ augment "/mamo:cont" {
+ leaf-list lflst1 {
+ type leafref {
+ path "../lf1";
+ }
+ }
+
+ leaf lf4 {
+ type leafref {
+ path "../lf1";
+ }
+ }
+
+ /* reference to not leaf element */
+ leaf lf6 {
+ type leafref {
+ path "../lflst1";
+ }
+ }
+
+ leaf lf7 {
+ type leafref {
+ path "../lf4";
+ }
+ }
+ }
+
+
+
+
+}
\ No newline at end of file
--- /dev/null
+module main-module {
+ namespace "main:module";
+
+ prefix "mainmod";
+ revision 2013-12-2 {
+ }
+
+ container cont {
+ leaf lf1 {
+ type uint32;
+ }
+
+ container cont1 {
+ leaf lf11 {
+ type boolean;
+ }
+ }
+
+ leaf lf2 {
+ type leafref {
+ path "../lf1";
+ }
+ }
+
+ leaf lf3 {
+ type leafref {
+ path "/cont/cont1/lf11";
+ }
+ }
+
+ /* reference to nonexisting leaf */
+ leaf lf5 {
+ type leafref {
+ path "/cont/lf";
+ }
+ }
+
+
+ }
+
+
+
+}
\ No newline at end of file
--- /dev/null
+<cont>
+ <cont1>
+ <lf11>true</lf11>
+ </cont1>
+ <lf3>true</lf3>
+</cont>
\ No newline at end of file
--- /dev/null
+<cont>
+ <lf7>200</lf7>
+</cont>
\ No newline at end of file
--- /dev/null
+<cont>
+ <lf5>137</lf5>
+</cont>
\ No newline at end of file
--- /dev/null
+<cont>
+ <lf6>44.33</lf6>
+</cont>
\ No newline at end of file
--- /dev/null
+<cont>
+ <lflst1>345</lflst1>
+ <lflst1>346</lflst1>
+ <lflst1>347</lflst1>
+</cont>
\ No newline at end of file
--- /dev/null
+<cont>
+ <lf1>121</lf1>
+ <lf2>121</lf2>
+</cont>
\ No newline at end of file
import javax.management.openmbean.SimpleType;
import java.lang.reflect.Method;
+import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Map;
resolverPlugins.put(Date.class.getCanonicalName(), new DateResolver());
resolverPlugins.put(Character.class.getCanonicalName(), new CharResolver());
resolverPlugins.put(BigInteger.class.getCanonicalName(), new BigIntegerResolver());
+ resolverPlugins.put(BigDecimal.class.getCanonicalName(), new BigDecimalResolver());
}
static interface Resolver {
}
}
+ static class BigDecimalResolver extends DefaultResolver {
+
+ @Override
+ protected Object parseObject(Class<?> type, String value) throws Exception {
+ return new BigDecimal(value);
+ }
+ }
+
static class CharResolver extends DefaultResolver {
@Override
checkTypeConfigAttribute(response);
checkTypedefs(response);
checkEnum(response);
+ checkBigDecimal(response);
edit("netconfMessages/editConfig_remove.xml");
verifyNoMoreInteractions(netconfOperationRouter);
}
+ private void checkBigDecimal(Element response) {
+ int size = response.getElementsByTagName("sleep-factor").getLength();
+ assertEquals(1, size);
+ }
+
private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException,
IOException {
DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID);
import com.google.common.collect.Sets;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+import javax.annotation.concurrent.ThreadSafe;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServerConnection;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
import org.opendaylight.controller.config.persist.api.Persister;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
-import javax.annotation.concurrent.ThreadSafe;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServerConnection;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
-import javax.net.ssl.SSLContext;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetSocketAddress;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Pattern;
-
/**
* Responsible for listening for notifications from netconf containing latest
* committed configuration that should be persisted, and also for loading last
long deadline = pollingStart + timeout;
while (System.currentTimeMillis() < deadline) {
attempt++;
- netconfClientDispatcher = new NetconfClientDispatcher(Optional.<SSLContext>absent(), nettyThreadgroup, nettyThreadgroup);
+ netconfClientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup);
try {
netconfClient = new NetconfClient(this.toString(), address, delay, netconfClientDispatcher);
} catch (IllegalStateException e) {
package org.opendaylight.controller.netconf.client;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.HashedWheelTimer;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;
+import java.io.Closeable;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.AbstractSslChannelInitializer;
+import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
import org.opendaylight.protocol.framework.AbstractDispatcher;
import org.opendaylight.protocol.framework.ReconnectStrategy;
import org.opendaylight.protocol.framework.SessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import java.io.Closeable;
-import java.net.InetSocketAddress;
-
public class NetconfClientDispatcher extends AbstractDispatcher<NetconfClientSession, NetconfClientSessionListener> implements Closeable {
private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class);
- private final Optional<SSLContext> maybeContext;
private final NetconfClientSessionNegotiatorFactory negotatorFactory;
private final HashedWheelTimer timer;
- public NetconfClientDispatcher(final Optional<SSLContext> maybeContext, EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
+ public NetconfClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
super(bossGroup, workerGroup);
- this.maybeContext = Preconditions.checkNotNull(maybeContext);
timer = new HashedWheelTimer();
this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer);
}
}
private void initialize(SocketChannel ch, Promise<NetconfClientSession> promise) {
- new ClientSslChannelInitializer(maybeContext, negotatorFactory, sessionListener).initialize(ch, promise);
+ new ClientChannelInitializer( negotatorFactory, sessionListener).initialize(ch, promise);
}
});
}
- private static class ClientSslChannelInitializer extends AbstractSslChannelInitializer {
+ private static class ClientChannelInitializer extends AbstractChannelInitializer {
private final NetconfClientSessionNegotiatorFactory negotiatorFactory;
private final NetconfClientSessionListener sessionListener;
- private ClientSslChannelInitializer(Optional<SSLContext> maybeContext,
- NetconfClientSessionNegotiatorFactory negotiatorFactory, NetconfClientSessionListener sessionListener) {
- super(maybeContext);
+ private ClientChannelInitializer(NetconfClientSessionNegotiatorFactory negotiatorFactory,
+ NetconfClientSessionListener sessionListener) {
this.negotiatorFactory = negotiatorFactory;
this.sessionListener = sessionListener;
}
+ @Override
+ public void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise) {
+ super.initialize(ch,promise);
+ }
+
@Override
protected void initializeAfterDecoder(SocketChannel ch, Promise<? extends NetconfSession> promise) {
ch.pipeline().addLast("negotiator", negotiatorFactory.getSessionNegotiator(new SessionListenerFactory() {
}, ch, promise));
}
- @Override
- protected void initSslEngine(SSLEngine sslEngine) {
- sslEngine.setUseClientMode(true);
- }
}
-
@Override
public void close() {
try {
package org.opendaylight.controller.netconf.client;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.Promise;
import java.io.IOException;
import java.net.InetSocketAddress;
-
-import javax.net.ssl.SSLContext;
-
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
import org.opendaylight.controller.netconf.util.handler.ssh.SshHandler;
import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker;
-import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory;
import org.opendaylight.protocol.framework.ProtocolHandlerFactory;
import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
import org.opendaylight.protocol.framework.SessionListener;
import org.opendaylight.protocol.framework.SessionListenerFactory;
-import com.google.common.base.Optional;
-
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.socket.SocketChannel;
-import io.netty.util.HashedWheelTimer;
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.Promise;
-
public class NetconfSshClientDispatcher extends NetconfClientDispatcher {
private AuthenticationHandler authHandler;
public NetconfSshClientDispatcher(AuthenticationHandler authHandler, EventLoopGroup bossGroup,
EventLoopGroup workerGroup) {
- super(Optional.<SSLContext> absent(), bossGroup, workerGroup);
+ super(bossGroup, workerGroup);
this.authHandler = authHandler;
this.timer = new HashedWheelTimer();
this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer);
}
- @Override
public Future<NetconfClientSession> createClient(InetSocketAddress address,
final NetconfClientSessionListener sessionListener, ReconnectStrategy strat) {
return super.createClient(address, strat, new PipelineInitializer<NetconfClientSession>() {
try {
Invoker invoker = Invoker.subsystem("netconf");
ch.pipeline().addFirst(new SshHandler(authenticationHandler, invoker));
- ch.pipeline().addLast("aggregator", new NetconfMessageAggregator(FramingMechanism.EOM));
- ch.pipeline().addLast(handlerFactory.getDecoders());
- initializeAfterDecoder(ch, promise);
- ch.pipeline().addLast("frameEncoder",
- FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM));
- ch.pipeline().addLast(handlerFactory.getEncoders());
+ super.initialize(ch,promise);
} catch (IOException e) {
throw new RuntimeException(e);
}
package org.opendaylight.controller.netconf.impl;
-import com.google.common.base.Optional;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.impl.util.DeserializerExceptionHandler;
-import org.opendaylight.controller.netconf.util.AbstractSslChannelInitializer;
+import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
import org.opendaylight.protocol.framework.AbstractDispatcher;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import java.net.InetSocketAddress;
-
public class NetconfServerDispatcher extends AbstractDispatcher<NetconfSession, NetconfServerSessionListener> {
- private final ServerSslChannelInitializer initializer;
+ private final ServerChannelInitializer initializer;
- public NetconfServerDispatcher(ServerSslChannelInitializer serverChannelInitializer, EventLoopGroup bossGroup,
+ public NetconfServerDispatcher(ServerChannelInitializer serverChannelInitializer, EventLoopGroup bossGroup,
EventLoopGroup workerGroup) {
super(bossGroup, workerGroup);
this.initializer = serverChannelInitializer;
});
}
- public static class ServerSslChannelInitializer extends AbstractSslChannelInitializer {
+ public static class ServerChannelInitializer extends AbstractChannelInitializer {
private final NetconfServerSessionNegotiatorFactory negotiatorFactory;
private final NetconfServerSessionListenerFactory listenerFactory;
- public ServerSslChannelInitializer(Optional<SSLContext> maybeContext,
- NetconfServerSessionNegotiatorFactory negotiatorFactory,
+ public ServerChannelInitializer(NetconfServerSessionNegotiatorFactory negotiatorFactory,
NetconfServerSessionListenerFactory listenerFactory) {
- super(maybeContext);
this.negotiatorFactory = negotiatorFactory;
this.listenerFactory = listenerFactory;
}
ch.pipeline().addLast("negotiator", negotiatorFactory.getSessionNegotiator(listenerFactory, ch, promise));
}
- @Override
- protected void initSslEngine(SSLEngine sslEngine) {
- sslEngine.setUseClientMode(false);
- }
}
}
*/
package org.opendaylight.controller.netconf.impl.osgi;
-import com.google.common.base.Optional;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.net.ssl.SSLContext;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-
public class NetconfImplActivator implements BundleActivator {
private static final Logger logger = LoggerFactory.getLogger(NetconfImplActivator.class);
eventLoopGroup = new NioEventLoopGroup();
- NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(
- Optional.<SSLContext>absent(), serverNegotiatorFactory, listenerFactory);
+ NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
+ serverNegotiatorFactory, listenerFactory);
dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup);
logger.info("Starting TCP netconf server at {}", address);
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import javax.management.ObjectName;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-
-import javax.management.ObjectName;
-import javax.net.ssl.SSLContext;
-import java.io.DataOutputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
import static com.google.common.base.Preconditions.checkNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
private static final int CONCURRENCY = 16;
private static EventLoopGroup nettyGroup = new NioEventLoopGroup();
- public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher(
- Optional.<SSLContext> absent(), nettyGroup, nettyGroup);
+ public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher( nettyGroup, nettyGroup);
@Mock
private YangStoreService yangStoreService;
NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
factoriesListener, commitNot, idProvider);
- NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(
- Optional.<SSLContext> absent(), serverNegotiatorFactory, listenerFactory);
+ NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(serverNegotiatorFactory, listenerFactory);
dispatch = new NetconfServerDispatcher(serverChannelInitializer, nettyGroup, nettyGroup);
ChannelFuture s = dispatch.createServer(netconfAddress);
package org.opendaylight.controller.netconf.impl;
-import com.google.common.base.Optional;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
-import javax.net.ssl.SSLContext;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-
public class NetconfDispatcherImplTest {
private EventLoopGroup nettyGroup;
NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
factoriesListener, commitNot, idProvider);
- NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(Optional.<SSLContext>absent(), serverNegotiatorFactory, listenerFactory);
+ NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(serverNegotiatorFactory, listenerFactory);
NetconfServerDispatcher dispatch = new NetconfServerDispatcher(
package org.opendaylight.controller.netconf.it;
-import com.google.common.base.Optional;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
import org.opendaylight.protocol.util.SSLUtil;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
public class NetconfITSecureTest extends AbstractConfigTest {
private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024);
nettyThreadgroup = new NioEventLoopGroup();
- dispatchS = createDispatcher(Optional.of(getSslContext()), factoriesListener);
+ dispatchS = createDispatcher(factoriesListener);
ChannelFuture s = dispatchS.createServer(tlsAddress);
s.await();
}
- private NetconfServerDispatcher createDispatcher(Optional<SSLContext> sslC,
- NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+ private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) {
SessionIdProvider idProvider = new SessionIdProvider();
NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
new HashedWheelTimer(5000, TimeUnit.MILLISECONDS), factoriesListener, idProvider);
NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
factoriesListener, commitNot, idProvider);
- NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(
- sslC, serverNegotiatorFactory, listenerFactory);
+ NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
+ serverNegotiatorFactory, listenerFactory);
return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
}
@Test
public void testSecure() throws Exception {
- NetconfClientDispatcher dispatch = new NetconfClientDispatcher(Optional.of(getSslContext()), nettyThreadgroup, nettyThreadgroup);
+ NetconfClientDispatcher dispatch = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup);
try (NetconfClient netconfClient = new NetconfClient("tls-client", tlsAddress, 4000, dispatch)) {
}
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import javax.management.ObjectName;
-import javax.net.ssl.SSLContext;
import javax.xml.parsers.ParserConfigurationException;
import junit.framework.Assert;
import org.junit.After;
commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
- dispatch = createDispatcher(Optional.<SSLContext> absent(), factoriesListener);
+ dispatch = createDispatcher(factoriesListener);
ChannelFuture s = dispatch.createServer(tcpAddress);
s.await();
- clientDispatcher = new NetconfClientDispatcher(Optional.<SSLContext>absent(), nettyThreadgroup, nettyThreadgroup);
+ clientDispatcher = new NetconfClientDispatcher( nettyThreadgroup, nettyThreadgroup);
}
- private NetconfServerDispatcher createDispatcher(Optional<SSLContext> sslC,
- NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+ private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) {
SessionIdProvider idProvider = new SessionIdProvider();
NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
new HashedWheelTimer(5000, TimeUnit.MILLISECONDS), factoriesListener, idProvider);
NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
factoriesListener, commitNot, idProvider);
- NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(
- sslC, serverNegotiatorFactory, listenerFactory);
+ NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
+ serverNegotiatorFactory, listenerFactory);
return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
}
private NetconfSSHServer server;
private static final Logger logger = LoggerFactory.getLogger(NetconfSSHActivator.class);
+ private static final String EXCEPTION_MESSAGE = "Netconf ssh bridge is not available.";
@Override
public void start(BundleContext context) throws Exception {
logger.trace("Starting netconf SSH bridge.");
- Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context);
- InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
- "TCP is not configured, netconf ssh bridge is not available.");
+ Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context,EXCEPTION_MESSAGE);
+ InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,EXCEPTION_MESSAGE);
if (sshSocketAddressOptional.isPresent()){
server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress);
private String id;
private ServerSession servSession;
private ServerConnection servconnection;
+ private String customHeader;
public IOThread (InputStream is, OutputStream os, String id,ServerSession ss, ServerConnection conn){
super.setName(id);
logger.trace("IOThread {} created", super.getName());
}
+ public IOThread (InputStream is, OutputStream os, String id,ServerSession ss, ServerConnection conn,String header){
+ this.inputStream = is;
+ this.outputStream = os;
+ this.servSession = ss;
+ this.servconnection = conn;
+ this.customHeader = header;
+ super.setName(id);
+ logger.trace("IOThread {} created", super.getName());
+ }
@Override
public void run() {
logger.trace("thread {} started", super.getName());
try {
+ if (this.customHeader!=null && !this.customHeader.equals("")){
+ this.outputStream.write(this.customHeader.getBytes());
+ logger.trace("adding {} header", this.customHeader);
+ }
IOUtils.copy(this.inputStream, this.outputStream);
} catch (Exception e) {
logger.error("inputstream -> outputstream copy error ",e);
private static final Logger logger = LoggerFactory.getLogger(SocketThread.class);
private ServerConnection conn = null;
private long sessionId;
+ private String currentUser;
+ private final String remoteAddressWithPort;
public static void start(Socket socket, InetSocketAddress clientAddress, long sessionId) throws IOException{
this.socket = socket;
this.clientAddress = clientAddress;
this.sessionId = sessionId;
+ this.remoteAddressWithPort = socket.getRemoteSocketAddress().toString().replaceFirst("/","");
}
netconf_ssh_input.start();
logger.trace("starting netconf_ssh_output thread");
- netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn);
+ final String customHeader = "["+currentUser+";"+remoteAddressWithPort+";ssh;;;;;;]\n";
+ netconf_ssh_output = new IOThread(ss.getStdout(),echoSocket.getOutputStream(),"output_thread_"+sessionId,ss,conn,customHeader);
netconf_ssh_output.setDaemon(false);
netconf_ssh_output.start();
public String initAuthentication(ServerConnection sc)
{
- return "";
+ logger.trace("Established connection with host {}",remoteAddressWithPort);
+ return "Established connection with host "+remoteAddressWithPort+"\r\n";
}
public String[] getRemainingAuthMethods(ServerConnection sc)
public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password)
{
- if (USER.equals(username) && PASSWORD.equals(password))
+ if (USER.equals(username) && PASSWORD.equals(password)){
+ currentUser = username;
+ logger.trace("user {}@{} authenticated",currentUser,remoteAddressWithPort);
return AuthenticationResult.SUCCESS;
+ }
+
return AuthenticationResult.FAILURE;
}
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
import org.opendaylight.controller.netconf.api.NetconfSession;
+import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.util.handler.NetconfHandlerFactory;
+import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
+import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory;
public abstract class AbstractChannelInitializer {
- public abstract void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise);
+ public void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise){
+ NetconfHandlerFactory handlerFactory = new NetconfHandlerFactory(new NetconfMessageFactory());
+ ch.pipeline().addLast("aggregator", new NetconfMessageAggregator(FramingMechanism.EOM));
+ ch.pipeline().addLast(handlerFactory.getDecoders());
+ initializeAfterDecoder(ch, promise);
+ ch.pipeline().addLast("frameEncoder", FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM));
+ ch.pipeline().addLast(handlerFactory.getEncoders());
+ }
protected abstract void initializeAfterDecoder(SocketChannel ch, Promise<? extends NetconfSession> promise);
+++ /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.util;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
-import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory;
-import org.opendaylight.protocol.framework.ProtocolHandlerFactory;
-import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
-import org.opendaylight.protocol.framework.ProtocolMessageEncoder;
-
-import com.google.common.base.Optional;
-
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.socket.SocketChannel;
-import io.netty.handler.ssl.SslHandler;
-import io.netty.util.concurrent.Promise;
-
-public abstract class AbstractSslChannelInitializer extends AbstractChannelInitializer {
-
- private final Optional<SSLContext> maybeContext;
- private final NetconfHandlerFactory handlerFactory;
-
- public AbstractSslChannelInitializer(Optional<SSLContext> maybeContext) {
- this.maybeContext = maybeContext;
- this.handlerFactory = new NetconfHandlerFactory(new NetconfMessageFactory());
- }
-
- @Override
- public void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise) {
- if (maybeContext.isPresent()) {
- initSsl(ch);
- }
-
- ch.pipeline().addLast("aggregator", new NetconfMessageAggregator(FramingMechanism.EOM));
- ch.pipeline().addLast(handlerFactory.getDecoders());
- initializeAfterDecoder(ch, promise);
- ch.pipeline().addLast("frameEncoder", FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM));
- ch.pipeline().addLast(handlerFactory.getEncoders());
- }
-
- private void initSsl(SocketChannel ch) {
- SSLEngine sslEngine = maybeContext.get().createSSLEngine();
- initSslEngine(sslEngine);
- final SslHandler handler = new SslHandler(sslEngine);
- ch.pipeline().addLast("ssl", handler);
- }
-
- protected abstract void initSslEngine(SSLEngine sslEngine);
-
- private static final class NetconfHandlerFactory extends ProtocolHandlerFactory<NetconfMessage> {
-
- public NetconfHandlerFactory(final NetconfMessageFactory msgFactory) {
- super(msgFactory);
- }
-
- @Override
- public ChannelHandler[] getEncoders() {
- return new ChannelHandler[] { new ProtocolMessageEncoder(this.msgFactory) };
- }
-
- @Override
- public ChannelHandler[] getDecoders() {
- return new ChannelHandler[] { new ProtocolMessageDecoder(this.msgFactory) };
- }
- }
-}
--- /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.util.handler;
+
+import io.netty.channel.ChannelHandler;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolHandlerFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
+import org.opendaylight.protocol.framework.ProtocolMessageEncoder;
+
+public class NetconfHandlerFactory extends ProtocolHandlerFactory<NetconfMessage> {
+
+ public NetconfHandlerFactory(final NetconfMessageFactory msgFactory) {
+ super(msgFactory);
+ }
+
+ @Override
+ public ChannelHandler[] getEncoders() {
+ return new ChannelHandler[] { new ProtocolMessageEncoder(this.msgFactory) };
+ }
+
+ @Override
+ public ChannelHandler[] getDecoders() {
+ return new ChannelHandler[] { new ProtocolMessageDecoder(this.msgFactory) };
+ }
+
+}
package org.opendaylight.controller.netconf.util.osgi;
import com.google.common.base.Optional;
-import org.opendaylight.protocol.util.SSLUtil;
-import org.osgi.framework.BundleContext;
-
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
import java.net.InetSocketAddress;
-
+import org.osgi.framework.BundleContext;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-public class NetconfConfigUtil {
+ public class NetconfConfigUtil {
private static final String PREFIX_PROP = "netconf.";
private enum InfixProp {
- tcp, tls, ssh
+ tcp, ssh
}
private static final String PORT_SUFFIX_PROP = ".port";
private static final String ADDRESS_SUFFIX_PROP = ".address";
- private static final String NETCONF_TLS_KEYSTORE_PROP = PREFIX_PROP + InfixProp.tls + ".keystore";
- private static final String NETCONF_TLS_KEYSTORE_PASSWORD_PROP = NETCONF_TLS_KEYSTORE_PROP + ".password";
-
public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound) {
- Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp);
+ Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound);
+
if (inetSocketAddressOptional.isPresent() == false) {
throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound);
}
return inetSocketAddressOptional.get();
}
- public static Optional<InetSocketAddress> extractSSHNetconfAddress(BundleContext context) {
- return extractSomeNetconfAddress(context, InfixProp.ssh);
- }
-
-
- public static Optional<TLSConfiguration> extractTLSConfiguration(BundleContext context) {
- Optional<InetSocketAddress> address = extractSomeNetconfAddress(context, InfixProp.tls);
- if (address.isPresent()) {
- String keystoreFileName = context.getProperty(NETCONF_TLS_KEYSTORE_PROP);
- File keystoreFile = new File(keystoreFileName);
- checkState(keystoreFile.exists() && keystoreFile.isFile() && keystoreFile.canRead(),
- "Keystore file %s does not exist or is not readable file", keystoreFileName);
- keystoreFile = keystoreFile.getAbsoluteFile();
- String keystorePassword = context.getProperty(NETCONF_TLS_KEYSTORE_PASSWORD_PROP);
- checkNotNull(keystoreFileName, "Property %s must be defined for tls netconf server",
- NETCONF_TLS_KEYSTORE_PROP);
- keystorePassword = keystorePassword != null ? keystorePassword : "";
- return Optional.of(new TLSConfiguration(address.get(), keystoreFile, keystorePassword));
- } else {
- return Optional.absent();
- }
- }
-
- public static class TLSConfiguration {
- private final InetSocketAddress address;
- private final File keystoreFile;
- private final String keystorePassword;
- private final SSLContext sslContext;
-
- TLSConfiguration(InetSocketAddress address, File keystoreFile, String keystorePassword) {
- this.address = address;
- this.keystoreFile = keystoreFile;
- this.keystorePassword = keystorePassword;
- try {
- try (InputStream keyStoreIS = new FileInputStream(keystoreFile)) {
- try (InputStream trustStoreIS = new FileInputStream(keystoreFile)) {
- sslContext = SSLUtil.initializeSecureContext("password", keyStoreIS, trustStoreIS, KeyManagerFactory.getDefaultAlgorithm());
- }
- }
- } catch (Exception e) {
- throw new RuntimeException("Cannot initialize ssl context for netconf file " + keystoreFile, e);
- }
- }
-
- public SSLContext getSslContext() {
- return sslContext;
- }
-
- public InetSocketAddress getAddress() {
- return address;
- }
-
- public File getKeystoreFile() {
- return keystoreFile;
- }
-
- public String getKeystorePassword() {
- return keystorePassword;
- }
+ public static Optional<InetSocketAddress> extractSSHNetconfAddress(BundleContext context, String exceptionMessage) {
+ return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage);
}
/**
* @param context
* from which properties are being read.
* @param infixProp
- * either tcp or tls
- * @return absent if address is missing, value if address and port are
- * valid.
+ * either tcp or ssh
+ * @return value if address and port are valid.
* @throws IllegalStateException
- * if address or port are invalid
+ * if address or port are invalid, or configuration is missing
*/
private static Optional<InetSocketAddress> extractSomeNetconfAddress(BundleContext context,
- InfixProp infixProp) {
+ InfixProp infixProp, String exceptionMessage) {
String address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
if (address == null) {
- return Optional.absent();
+ throw new IllegalStateException("Cannot find initial netconf configuration for parameter "
+ +PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP
+ +" in config.ini. "+exceptionMessage);
}
String portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
String portString = context.getProperty(portKey);
<name>test1</name>
+ <sleep-factor>
+ 2.00
+ </sleep-factor>
+
<extended>
1
</extended>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
import org.openflow.protocol.OFBarrierReply;
import org.openflow.protocol.OFBarrierRequest;
import org.openflow.protocol.OFEchoReply;
+import org.openflow.protocol.OFEchoRequest;
import org.openflow.protocol.OFError;
import org.openflow.protocol.OFFeaturesReply;
import org.openflow.protocol.OFFlowMod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
public class SwitchHandler implements ISwitch {
private static final Logger logger = LoggerFactory.getLogger(SwitchHandler.class);
private static final int SWITCH_LIVENESS_TIMER = 5000;
break;
case ECHO_REQUEST:
OFEchoReply echoReply = (OFEchoReply) factory.getMessage(OFType.ECHO_REPLY);
+
+ byte []payload = ((OFEchoRequest)msg).getPayload();
+ if (payload != null && payload.length != 0 ) {
+ // the response must have the same payload as the request
+ echoReply.setPayload(payload);
+ echoReply.setLength( (short)(echoReply.getLength() + payload.length) );
+ }
+
// respond immediately
asyncSendNow(echoReply, msg.getXid());
@Override
public String toString() {
- return "Match[" + fields.values() + "]";
+ StringBuilder builder = new StringBuilder();
+ builder.append("Match [fields=");
+ builder.append(fields);
+ builder.append(", matches=");
+ builder.append(matches);
+ builder.append("]");
+ return builder.toString();
}
+
}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>