-.idea/\r
-target/\r
-*.class\r
-*.iml\r
-**/target\r
-**/bin\r
-dist\r
-**/logs\r
-products\r
-repository\r
-workspace\r
-*~\r
-target\r
-.classpath\r
-.project\r
-.settings\r
-MANIFEST.MF\r
-xtend-gen\r
+.idea/
+target/
+*.class
+*.iml
+**/target
+**/bin
+dist
+**/logs
+products
+repository
+workspace
+*~
+target
+.classpath
+.project
+.settings
+MANIFEST.MF
+xtend-gen
yang-gen-sal
yang-gen-config
-.externalToolBuilders\r
-maven-eclipse.xml\r
+.externalToolBuilders
+maven-eclipse.xml
.metadata/
.checkstyle
+maven-metadata-local.xml
+*.pyc
+/.pydevproject
+*.log
+.tox/
+++ /dev/null
-/*
- * Copyright (c) 2015 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.openflowplugin.applications.bulk.o.matic;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.SalBulkFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Created by mirehak on 6/8/15.
- */
-public class BulkOMaticProviderImpl implements BulkOMaticProvider {
-
- private static final Logger LOG = LoggerFactory.getLogger(BulkOMaticProviderImpl.class);
-
- private final BindingAwareBroker.RpcRegistration<SalBulkFlowService> serviceRpcRegistration;
-
- public BulkOMaticProviderImpl(RpcProviderRegistry rpcRegistry, DataBroker dataBroker) {
- LOG.info("creating bulk-o-matic");
- SalFlowService flowService = rpcRegistry.getRpcService(SalFlowService.class);
- SalBulkFlowService bulkOMaticService = new SalBulkFlowServiceImpl(flowService, dataBroker);
- bulkOMaticService.register();
- serviceRpcRegistration = rpcRegistry.addRpcImplementation(SalBulkFlowService.class, bulkOMaticService);
- }
-
- @Override
- public void close() {
- LOG.info("destroying bulk-o-matic");
- serviceRpcRegistration.close();
- }
-}
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.*;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.Future;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.AddFlowsDsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.AddFlowsRpcInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.BulkFlowBaseContentGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.FlowRpcAddMultipleInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.FlowRpcAddTestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.FlowTestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.ReadFlowTestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsDsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.RemoveFlowsRpcInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.SalBulkFlowService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.bulk.flow.service.rev150608.bulk.flow.ds.list.grouping.BulkFlowDsItem;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.*;
+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.RemoveFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import javax.management.*;
-import java.lang.management.ManagementFactory;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ForkJoinPool;
-import java.util.concurrent.Future;
-
/**
* Simple implementation providing bulk flows operations.
*/
private final SalFlowService flowService;
private final DataBroker dataBroker;
- private FlowCounter flowCounterBeanImpl = new FlowCounter();
+ private final FlowCounter flowCounterBeanImpl = new FlowCounter();
private final ExecutorService fjService = new ForkJoinPool();
public SalBulkFlowServiceImpl(SalFlowService flowService, DataBroker dataBroker) {
this.flowService = Preconditions.checkNotNull(flowService);
this.dataBroker = Preconditions.checkNotNull(dataBroker);
+ register();
}
@Override
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.bulk.o.matic.rev150608;
-import org.opendaylight.openflowplugin.applications.bulk.o.matic.BulkOMaticProviderImpl;
+import org.opendaylight.controller.sal.common.util.NoopAutoCloseable;
-public class BulkOMaticModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.bulk.o.matic.rev150608.AbstractBulkOMaticModule {
+/**
+ * @deprecated Replaced by blueprint wiring
+ */
+@Deprecated
+public class BulkOMaticModule extends AbstractBulkOMaticModule {
public BulkOMaticModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
super(identifier, dependencyResolver);
}
super(identifier, dependencyResolver, oldModule, oldInstance);
}
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
@Override
public java.lang.AutoCloseable createInstance() {
- return new BulkOMaticProviderImpl(getRpcRegistryDependency(), getDataBrokerDependency());
+ // Instances are created via blueprint so this in a no-op.
+ return NoopAutoCloseable.INSTANCE;
}
}
* Do not modify this file unless it is present under src/main directory
*/
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.bulk.o.matic.rev150608;
-public class BulkOMaticModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.bulk.o.matic.rev150608.AbstractBulkOMaticModuleFactory {
+
+/**
+ * @deprecated Replaced by blueprint wiring
+ */
+@Deprecated
+public class BulkOMaticModuleFactory extends AbstractBulkOMaticModuleFactory {
}
~ 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
+
+ NOTE: This file is deprecated as wiring is now done via blueprint. This file is kept for
+ backwards compatibility. Runtime modifications are not honored.
-->
<!-- vi: set et smarttab sw=4 tabstop=4: -->
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" odl:type="pingpong"/>
+
+ <odl:rpc-service id="flowService"
+ interface="org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService"/>
+
+ <bean id="bulkFlowService" class="org.opendaylight.openflowplugin.applications.bulk.o.matic.SalBulkFlowServiceImpl">
+ <argument ref="flowService"/>
+ <argument ref="dataBroker"/>
+ </bean>
+
+ <odl:rpc-implementation ref="bulkFlowService"/>
+</blueprint>
\ No newline at end of file
identity bulk-o-matic {
base "config:module-type";
config:java-name-prefix BulkOMatic;
+ status deprecated;
}
augment "/config:modules/config:module/config:configuration" {
<type>xml</type>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>statistics-manager-config</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
-
<dependency>
<groupId>org.opendaylight.openflowplugin.model</groupId>
<artifactId>model-flow-base</artifactId>
<bundle>mvn:org.opendaylight.openflowplugin.applications/inventory-manager/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.applications/forwardingrules-manager/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
- <configfile finalname="${config.configfile.directory}/${config.statistics.manager.configfile}">mvn:org.opendaylight.openflowplugin.applications/statistics-manager-config/{{VERSION}}/xml/config</configfile>
</feature>
</features>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (c) 2015 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
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>applications</artifactId>
- <version>0.3.0-SNAPSHOT</version>
- </parent>
-
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>forwardingrules-manager-config</artifactId>
- <description>Configuration files for forwarding rules manager</description>
- <packaging>jar</packaging>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-artifacts</id>
- <goals>
- <goal>attach-artifact</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <artifacts>
- <artifact>
- <file>${project.build.directory}/classes/initial/30-forwardingrules-manager.xml
- </file>
- <type>xml</type>
- <classifier>config</classifier>
- </artifact>
- </artifacts>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
- Copyright (c) 2015 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
--->
-<snapshot>
- <configuration>
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:frm="urn:opendaylight:params:xml:ns:yang:openflowplugin:app:forwardingrules-manager">
- frm:forwardingrules-manager
- </type>
- <name>forwardingrules-manager</name>
-
- <data-broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
- binding:binding-async-data-broker
- </type>
- <name>binding-data-broker</name>
- </data-broker>
-
- <rpc-registry>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
- binding:binding-rpc-registry
- </type>
- <name>binding-rpc-broker</name>
- </rpc-registry>
- <forwarding-manager-settings>
- <stale-marking-enabled>false</stale-marking-enabled>
- <reconciliation-retry-count>5</reconciliation-retry-count>
- </forwarding-manager-settings>
- <entity-ownership-service>
- <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
- <name>entity-ownership-service</name>
- </entity-ownership-service>
- </module>
- </modules>
- </data>
- </configuration>
-
- <required-capabilities>
- <capability>
- urn:opendaylight:params:xml:ns:yang:openflowplugin:app:forwardingrules-manager?module=forwardingrules-manager&revision=2014-09-25
- </capability>
- <capability>
- urn:opendaylight:flow:service?module=sal-flow&revision=2013-08-19
- </capability>
- <capability>
- urn:opendaylight:group:service?module=sal-group&revision=2013-09-18
- </capability>
- <capability>
- urn:opendaylight:meter:service?module=sal-meter&revision=2013-09-18
- </capability>
- <capability>
- urn:opendaylight:port:service?module=sal-port&revision=2013-11-07
- </capability>
- <capability>
- urn:opendaylight:queue:service?module=sal-queue&revision=2015-03-05
- </capability>
- <capability>
- urn:opendaylight:table:service?module=sal-table&revision=2013-10-26
- </capability>
- <capability>
- urn:opendaylight:params:xml:ns:yang:controller:config:distributed-entity-ownership-service?module=distributed-entity-ownership-service&revision=2015-08-10
- </capability>
- </required-capabilities>
-
-</snapshot>
-
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>config-api</artifactId>
+ <artifactId>sal-common-util</artifactId>
</dependency>
<dependency>
+++ /dev/null
-/**
- * Copyright (c) 2015 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.openflowplugin.applications.config.yang.forwardingrules_manager;
-
-import org.opendaylight.openflowplugin.applications.frm.impl.ForwardingRulesManagerConfig;
-import org.opendaylight.openflowplugin.applications.frm.impl.ForwardingRulesManagerImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ForwardingRulesManagerModule extends org.opendaylight.openflowplugin.applications.config.yang.forwardingrules_manager.AbstractForwardingRulesManagerModule {
-
- private static final Logger LOG = LoggerFactory.getLogger(ForwardingRulesManagerModule.class);
- private static final boolean ENABLE_FGM_STALE_MARKING = false;
- private static final int RECONCILIATION_RETRY_COUNT = 5;
-
- public ForwardingRulesManagerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public ForwardingRulesManagerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.openflowplugin.applications.config.yang.forwardingrules_manager.ForwardingRulesManagerModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- LOG.info("FRM module initialization.");
- final ForwardingRulesManagerConfig config = readConfig();
- final ForwardingRulesManagerImpl forwardingrulessManagerProvider =
- new ForwardingRulesManagerImpl(getDataBrokerDependency(), getRpcRegistryDependency(), config, getEntityOwnershipServiceDependency());
- forwardingrulessManagerProvider.start();
- LOG.info("FRM module started successfully.");
- return new AutoCloseable() {
- @Override
- public void close() throws Exception {
- try {
- forwardingrulessManagerProvider.close();
- } catch (final Exception e) {
- LOG.warn("Unexpected error by stopping FRM", e);
- }
- LOG.info("FRM module stopped.");
- }
- };
- }
-
- private ForwardingRulesManagerConfig readConfig(){
-
- final ForwardingRulesManagerConfig.ForwardingRulesManagerConfigBuilder fwdRulesMgrCfgBuilder = ForwardingRulesManagerConfig.builder();
-
- if (getForwardingManagerSettings() != null && getForwardingManagerSettings().getStaleMarkingEnabled() != null){
- fwdRulesMgrCfgBuilder.setStaleMarkingEnabled(getForwardingManagerSettings().getStaleMarkingEnabled());
- }
- else{
- LOG.warn("Could not load XML configuration file via ConfigSubsystem! Fallback to default config value(s)");
- fwdRulesMgrCfgBuilder.setStaleMarkingEnabled(ENABLE_FGM_STALE_MARKING);
- }
-
- if(getForwardingManagerSettings() != null && getForwardingManagerSettings().getReconciliationRetryCount()>0){
- fwdRulesMgrCfgBuilder.setReconciliationRetryCount(getForwardingManagerSettings().getReconciliationRetryCount());
- }
- else{
- LOG.warn("Could not load XML configuration file via ConfigSubsystem for reconciliation retry! " +
- "Fallback to default config value(s)");
- fwdRulesMgrCfgBuilder.setReconciliationRetryCount(RECONCILIATION_RETRY_COUNT);
- }
-
-
-
- return fwdRulesMgrCfgBuilder.build();
-
- }
-
-}
+++ /dev/null
-/**
- * Copyright (c) 2015 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
- */
-
-/*
-* Generated file
-*
-* Generated from: yang module name: forwardingrules-manager yang module local name: forwardingrules-manager
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Thu Apr 23 19:20:17 CEST 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.openflowplugin.applications.config.yang.forwardingrules_manager;
-public class ForwardingRulesManagerModuleFactory extends org.opendaylight.openflowplugin.applications.config.yang.forwardingrules_manager.AbstractForwardingRulesManagerModuleFactory {
-
-}
package org.opendaylight.openflowplugin.applications.frm;
import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
*
* Created: Aug 26, 2014
*/
-public interface FlowNodeReconciliation extends ClusteredDataChangeListener, AutoCloseable {
+public interface FlowNodeReconciliation extends ClusteredDataTreeChangeListener<FlowCapableNode>, AutoCloseable {
/**
* Method contains Node registration to {@link ForwardingRulesManager} functionality
package org.opendaylight.openflowplugin.applications.frm;
-import org.opendaylight.openflowplugin.applications.frm.impl.ForwardingRulesManagerConfig;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
-
-import org.opendaylight.openflowplugin.applications.frm.impl.FlowNodeConnectorInventoryTranslatorImpl;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.openflowplugin.applications.frm.impl.FlowNodeConnectorInventoryTranslatorImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.forwardingrules.manager.config.rev160511.ForwardingRulesManagerConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
* @return True if owner, else false
*/
public boolean isNodeOwner(InstanceIdentifier<FlowCapableNode> ident);
-
+
/**
* Content definition method and prevent code duplicity
* @return FlowNodeConnectorInventoryTranslatorImpl
package org.opendaylight.openflowplugin.applications.frm.impl;
+import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
+
import java.util.concurrent.Callable;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+
+import org.opendaylight.controller.md.sal.binding.api.*;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.StaleGroup;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.StaleGroupKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.Nonnull;
+
/**
* forwardingrules-manager
private final ForwardingRulesManager provider;
public static final String SEPARATOR = ":";
- private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private ListenerRegistration<FlowNodeReconciliationImpl> listenerRegistration;
+
+ private static final InstanceIdentifier<FlowCapableNode> II_TO_FLOW_CAPABLE_NODE
+ = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class)
+ .augmentation(FlowCapableNode.class)
+ .build();
public FlowNodeReconciliationImpl (final ForwardingRulesManager manager, final DataBroker db) {
this.provider = Preconditions.checkNotNull(manager, "ForwardingRulesManager can not be null!");
final InstanceIdentifier<FlowCapableNode> flowNodeWildCardIdentifier = InstanceIdentifier.create(Nodes.class)
.child(Node.class).augmentation(FlowCapableNode.class);
+ final DataTreeIdentifier<FlowCapableNode> treeId =
+ new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, flowNodeWildCardIdentifier);
+
+ try {
SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(ForwardingRulesManagerImpl.STARTUP_LOOP_TICK,
ForwardingRulesManagerImpl.STARTUP_LOOP_MAX_RETRIES);
- try {
- listenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<DataChangeListener>>() {
+
+ listenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<FlowNodeReconciliationImpl>>() {
@Override
- public ListenerRegistration<DataChangeListener> call() throws Exception {
- return db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- flowNodeWildCardIdentifier, FlowNodeReconciliationImpl.this, DataChangeScope.BASE);
+ public ListenerRegistration<FlowNodeReconciliationImpl> call() throws Exception {
+ return dataBroker.registerDataTreeChangeListener(treeId, FlowNodeReconciliationImpl.this);
}
});
} catch (Exception e) {
}
@Override
- public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
- Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
- /* All DataObjects for create */
- final Set<InstanceIdentifier<?>> createdData = changeEvent.getCreatedData() != null
- ? changeEvent.getCreatedData().keySet() : Collections.<InstanceIdentifier<?>> emptySet();
- /* All DataObjects for remove */
- final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
- ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>> emptySet();
- /* All updated DataObjects */
- final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
- ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
-
- for (InstanceIdentifier<?> entryKey : removeData) {
- final InstanceIdentifier<FlowCapableNode> nodeIdent = entryKey
- .firstIdentifierOf(FlowCapableNode.class);
- if ( ! nodeIdent.isWildcarded()) {
- flowNodeDisconnected(nodeIdent);
+ public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<FlowCapableNode>> changes) {
+ Preconditions.checkNotNull(changes, "Changes may not be null!");
+
+ for (DataTreeModification<FlowCapableNode> change : changes) {
+ final InstanceIdentifier<FlowCapableNode> key = change.getRootPath().getRootIdentifier();
+ final DataObjectModification<FlowCapableNode> mod = change.getRootNode();
+ final InstanceIdentifier<FlowCapableNode> nodeIdent =
+ key.firstIdentifierOf(FlowCapableNode.class);
+
+ switch (mod.getModificationType()) {
+ case DELETE:
+ if (mod.getDataAfter() == null) {
+ remove(key, mod.getDataBefore(), nodeIdent);
+ }
+ break;
+ case SUBTREE_MODIFIED:
+ //NO-OP since we donot need to reconciliate on Node-updated
+ break;
+ case WRITE:
+ if (mod.getDataBefore() == null) {
+ add(key, mod.getDataAfter(), nodeIdent);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
}
}
- for (InstanceIdentifier<?> entryKey : createdData) {
- final InstanceIdentifier<FlowCapableNode> nodeIdent = entryKey
- .firstIdentifierOf(FlowCapableNode.class);
+ }
+
+
+
+ public void remove(InstanceIdentifier<FlowCapableNode> identifier, FlowCapableNode del,
+ InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ if(compareInstanceIdentifierTail(identifier,II_TO_FLOW_CAPABLE_NODE)){
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Node removed: {}",nodeIdent.firstKeyOf(Node.class).getId().getValue());
+ }
+
if ( ! nodeIdent.isWildcarded()) {
- flowNodeConnected(nodeIdent);
+ flowNodeDisconnected(nodeIdent);
}
+
}
+ }
- // FIXME: just a hack to cover DS/operational dirty start
- // if all conventional ways failed and there is update
- if (removeData.isEmpty() && createdData.isEmpty() && updateData.size() == 1) {
- for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : updateData.entrySet()) {
- // and only if this update covers top element (flow-capable-node)
- if (FlowCapableNode.class.equals(entry.getKey().getTargetType())) {
- final InstanceIdentifier<FlowCapableNode> nodeIdent = entry.getKey()
- .firstIdentifierOf(FlowCapableNode.class);
- if (!nodeIdent.isWildcarded()) {
- // then force registration to local node cache and reconcile
- flowNodeConnected(nodeIdent, true);
- }
- }
+ public void add(InstanceIdentifier<FlowCapableNode> identifier, FlowCapableNode add,
+ InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ if(compareInstanceIdentifierTail(identifier,II_TO_FLOW_CAPABLE_NODE)){
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Node added: {}",nodeIdent.firstKeyOf(Node.class).getId().getValue());
+ }
+
+ if ( ! nodeIdent.isWildcarded()) {
+ flowNodeConnected(nodeIdent);
}
}
}
}
-
-
-
+ private boolean compareInstanceIdentifierTail(InstanceIdentifier<?> identifier1,
+ InstanceIdentifier<?> identifier2) {
+ return Iterables.getLast(identifier1.getPathArguments()).equals(Iterables.getLast(identifier2.getPathArguments()));
+ }
}
+++ /dev/null
-/**
- * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.openflowplugin.applications.frm.impl;
-
-/**
- * Created by efiijjp on 10/14/2015.
- */
-public class ForwardingRulesManagerConfig {
-
- private final boolean m_staleMarkingEnabled;
- private final int m_reconciliationRetryCount;
-
- private ForwardingRulesManagerConfig(ForwardingRulesManagerConfigBuilder builder){
- m_staleMarkingEnabled = builder.isStaleMarkingEnabled();
- m_reconciliationRetryCount = builder.getReconciliationRetryCount();
- }
-
- public boolean isStaleMarkingEnabled(){
- return m_staleMarkingEnabled;
- }
-
- public int getReconciliationRetryCount() {
- return m_reconciliationRetryCount;
- }
-
-
- public static ForwardingRulesManagerConfigBuilder builder(){
- return new ForwardingRulesManagerConfigBuilder();
- }
-
-
-
- public static class ForwardingRulesManagerConfigBuilder {
- private boolean staleMarkingEnabled ;
- private int reconciliationRetryCount ;
-
- public boolean isStaleMarkingEnabled(){
- return staleMarkingEnabled;
- }
- public int getReconciliationRetryCount() {return reconciliationRetryCount;}
-
- public void setStaleMarkingEnabled(boolean staleMarkingEnabledFlag){
- staleMarkingEnabled = staleMarkingEnabledFlag;
- }
-
- public void setReconciliationRetryCount(int retryCount ){
- reconciliationRetryCount = retryCount;
- }
-
- public ForwardingRulesManagerConfig build(){
- return new ForwardingRulesManagerConfig(this);
- }
- }
-
-}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.CheckedFuture;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
-
-import com.google.common.util.concurrent.CheckedFuture;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.forwardingrules.manager.config.rev160511.ForwardingRulesManagerConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
this.tableListener = new TableForwarder(this, dataService);
this.nodeListener = new FlowNodeReconciliationImpl(this, dataService);
- flowNodeConnectorInventoryTranslatorImpl =
+ flowNodeConnectorInventoryTranslatorImpl =
new FlowNodeConnectorInventoryTranslatorImpl(this,dataService);
LOG.info("ForwardingRulesManager has started successfully.");
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
+ <reference id="rpcRegistry" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"/>
+ <reference id="entityOwnershipService" interface="org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService"/>
+
+ <odl:clustered-app-config id="frmConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.forwardingrules.manager.config.rev160511.ForwardingRulesManagerConfig"/>
+
+ <bean id="frmManager" class="org.opendaylight.openflowplugin.applications.frm.impl.ForwardingRulesManagerImpl"
+ init-method="start" destroy-method="close">
+ <argument ref="dataBroker"/>
+ <argument ref="rpcRegistry"/>
+ <argument ref="frmConfig"/>
+ <argument ref="entityOwnershipService"/>
+ </bean>
+</blueprint>
\ No newline at end of file
+++ /dev/null
-module forwardingrules-manager {
-
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:openflowplugin:app:forwardingrules-manager";
- prefix "frm";
-
- import config { prefix config; revision-date 2013-04-05; }
- import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
- import opendaylight-entity-ownership-service { prefix eos; }
-
- description
- "This module contains the base YANG definitions for
- forwardingrules-manager implementation.";
-
- revision "2014-09-25" {
- description
- "Initial revision.";
- }
-
- identity forwardingrules-manager {
- base config:module-type;
- config:java-name-prefix ForwardingRulesManager;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case forwardingrules-manager {
- when "/config:modules/config:module/config:type = 'forwardingrules-manager'";
-
- container rpc-registry {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity mdsal:binding-rpc-registry;
- }
- }
- }
-
- container data-broker {
- uses config:service-ref {
- refine type {
- mandatory false;
- config:required-identity mdsal:binding-async-data-broker;
- }
- }
- }
-
- container forwarding-manager-settings {
- leaf stale-marking-enabled {
- type boolean;
- }
- leaf reconciliation-retry-count {
- type uint16;
- }
-
- }
-
- container entity-ownership-service {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity eos:entity-ownership-service;
- }
- }
- }
-
- }
- }
-
-}
--- /dev/null
+module forwarding-rules-manager-config {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:openflowplugin:app:forwardingrules-manager:config";
+ prefix "frm";
+
+ description
+ "Configuration for Forwarding Rules Manager application..";
+
+ revision "2016-05-11" {
+ description
+ "Initial revision.";
+ }
+
+ container forwarding-rules-manager-config {
+ leaf stale-marking-enabled {
+ type boolean;
+ default false;
+ }
+
+ leaf reconciliation-retry-count {
+ type uint16;
+ default 5;
+ }
+ }
+}
\ No newline at end of file
*/
package test.mock;
+import static org.junit.Assert.assertEquals;
+import java.util.Collections;
+import java.util.List;
import org.junit.Test;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.openflowplugin.applications.frm.impl.ForwardingRulesManagerConfig;
import org.opendaylight.openflowplugin.applications.frm.impl.ForwardingRulesManagerImpl;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.StaleFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.StaleFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.StaleFlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
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.IpMatchBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
import test.mock.util.EntityOwnershipServiceMock;
import test.mock.util.FRMTest;
import test.mock.util.RpcProviderRegistryMock;
import test.mock.util.SalFlowServiceMock;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
public class FlowListenerTest extends FRMTest {
RpcProviderRegistry rpcProviderRegistryMock = new RpcProviderRegistryMock();
EntityOwnershipService eos = new EntityOwnershipServiceMock();
package test.mock.util;
-import org.opendaylight.openflowplugin.applications.frm.impl.ForwardingRulesManagerConfig;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.forwardingrules.manager.config.rev160511.ForwardingRulesManagerConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.forwardingrules.manager.config.rev160511.ForwardingRulesManagerConfigBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public abstract class FRMTest extends AbstractDataBrokerTest {
}
public ForwardingRulesManagerConfig getConfig(){
- ForwardingRulesManagerConfig.ForwardingRulesManagerConfigBuilder cfgBuilder =
- new ForwardingRulesManagerConfig.ForwardingRulesManagerConfigBuilder();
+ ForwardingRulesManagerConfigBuilder cfgBuilder = new ForwardingRulesManagerConfigBuilder();
cfgBuilder.setStaleMarkingEnabled(false);
+ cfgBuilder.setReconciliationRetryCount(0);
return cfgBuilder.build();
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>applications</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.opendaylight.openflowplugin.applications</groupId>
+ <artifactId>forwardingrules-sync</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-common</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>concepts</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.sonar-plugins.java</groupId>
+ <artifactId>sonar-jacoco-listeners</artifactId>
+ <version>${sonar-jacoco-listeners.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/openflowplugin.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/openflowplugin.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_OpenFlow_Plugin:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+
+</project>
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync;
+
+import java.util.concurrent.Future;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ * Represents a configuration item add-contract for device.
+ */
+public interface ForwardingRulesAddCommitter<D extends DataObject, A extends DataObject> {
+
+ /**
+ * Method adds the DataObject which is identified by InstanceIdentifier
+ * to device.
+ *
+ * @param identifier - the whole path to new DataObject
+ * @param add - new DataObject
+ * @param nodeIdent - Node InstanceIdentifier
+ */
+ Future<RpcResult<A>> add(InstanceIdentifier<D> identifier, D add, InstanceIdentifier<FlowCapableNode> nodeIdent);
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2014 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.openflowplugin.applications.frsync;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Represents configuration item contract for device.
+ * Combining add/update/remove commiters into single one.
+ */
+public interface ForwardingRulesCommitter<D extends DataObject, A extends DataObject, R extends DataObject, U extends DataObject>
+ extends ForwardingRulesAddCommitter<D, A>, ForwardingRulesRemoveCommitter<D, R>, ForwardingRulesUpdateCommitter<D, U> {
+}
+
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync;
+
+import java.util.concurrent.Future;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ * Represents a configuration item remove-contract for device.
+ */
+public interface ForwardingRulesRemoveCommitter<D extends DataObject, R extends DataObject> {
+
+ /**
+ * Method removes DataObject which is identified by InstanceIdentifier
+ * from device.
+ *
+ * @param identifier - the whole path to DataObject
+ * @param del - DataObject for removing
+ * @param nodeIdent - Node InstanceIdentifier
+ */
+ Future<RpcResult<R>> remove(InstanceIdentifier<D> identifier, D del, InstanceIdentifier<FlowCapableNode> nodeIdent);
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync;
+
+import java.util.concurrent.Future;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ * Represents a configuration item update-contract for device.
+ */
+public interface ForwardingRulesUpdateCommitter<D extends DataObject, U extends DataObject> {
+
+ /**
+ * Method updates the original DataObject to the update DataObject
+ * in device. Both are identified by same InstanceIdentifier
+ *
+ * @param identifier - the whole path to DataObject
+ * @param original - original DataObject (for update)
+ * @param update - changed DataObject (contain updates)
+ * @param nodeIdent - Node InstanceIdentifier
+ */
+ Future<RpcResult<U>> update(InstanceIdentifier<D> identifier, D original, D update,
+ InstanceIdentifier<FlowCapableNode> nodeIdent);
+
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync;
+
+import java.util.EventListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Unifying listener for data and event changes on node.
+ */
+public interface NodeListener<T extends DataObject> extends EventListener, DataTreeChangeListener<T> {
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync;
+
+import java.util.concurrent.Semaphore;
+import javax.annotation.Nonnull;
+
+/**
+ * Proposal for how a key based semaphore provider should look like.
+ * <ul>
+ * <li>thread safe</li>
+ * <li>garbage-collect unused semaphores</li>
+ * <li>for the same key there must be always only one semaphore available</li>
+ * </ul>
+ *
+ *
+ * usage:
+ * <pre>
+ * final Semaphore guard = semaphoreKeeper.summonGuard(key);
+ * guard.acquire();
+ * // guard protected logic ...
+ * guard.release();
+ * </pre>
+ *
+ * @param <K> key type
+ */
+
+public interface SemaphoreKeeper<K> {
+ /**
+ * @param key semaphore identifier
+ * @return new or existing semaphore for given key, for one key there is always only one semaphore available
+ */
+ Semaphore summonGuard(@Nonnull K key);
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.openflowplugin.applications.frsync.impl.strategy.SynchronizationDiffInput;
+import org.opendaylight.openflowplugin.applications.frsync.util.SyncCrudCounters;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ * Prescribes common synchronization plan execution strategy.
+ * Implementations should be stateless.
+ */
+public interface SyncPlanPushStrategy {
+
+ /**
+ * @param resultVehicle bootstrap future - execution will chain it's async calls to this one
+ * @param diffInput wraps all diff data required for any strategy ({add,remove,update} x {flow,group,meter})
+ * @param counters reference to internal one-shot statistics - summary off successfully pushed items
+ * shall be recorded here
+ * @return last future of the chain
+ */
+ ListenableFuture<RpcResult<Void>> executeSyncStrategy(ListenableFuture<RpcResult<Void>> resultVehicle,
+ SynchronizationDiffInput diffInput,
+ SyncCrudCounters counters);
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Device synchronization API.
+ */
+public interface SyncReactor {
+ /**
+ * @param flowcapableNodePath path to openflow augmentation of node
+ * @param configTree configured node
+ * @param operationalTree device reflection
+ * @param dsType type of DS change
+ * @return synchronization outcome
+ */
+ ListenableFuture<Boolean> syncup(final InstanceIdentifier<FlowCapableNode> flowcapableNodePath,
+ final FlowCapableNode configTree, final FlowCapableNode operationalTree,
+ final LogicalDatastoreType dsType) throws InterruptedException;
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.dao;
+
+import com.google.common.base.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+/**
+ * Implementation of data access object for {@link FlowCapableNode}.
+ * Contains pair of snapshot and odl DAOs.
+ */
+public class FlowCapableNodeCachedDao implements FlowCapableNodeDao {
+
+ private final FlowCapableNodeDao snapshotDao;
+ private final FlowCapableNodeDao odlDao;
+
+ public FlowCapableNodeCachedDao(FlowCapableNodeDao snapshotDao, FlowCapableNodeDao odlDao) {
+ this.snapshotDao = snapshotDao;
+ this.odlDao = odlDao;
+ }
+
+ public Optional<FlowCapableNode> loadByNodeId(@Nonnull NodeId nodeId) {
+ final Optional<FlowCapableNode> node = snapshotDao.loadByNodeId(nodeId);
+
+ if (node.isPresent()) {
+ return node;
+ }
+
+ return odlDao.loadByNodeId(nodeId);
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.dao;
+
+import com.google.common.base.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+/**
+ * Data access object for {@link FlowCapableNode}.
+ */
+public interface FlowCapableNodeDao {
+ Optional<FlowCapableNode> loadByNodeId(@Nonnull NodeId nodeId);
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.dao;
+
+import com.google.common.base.Optional;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of data access object for ODL {@link FlowCapableNode}.
+ */
+public class FlowCapableNodeOdlDao implements FlowCapableNodeDao {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FlowCapableNodeOdlDao.class);
+
+ private static final InstanceIdentifier<Nodes> NODES_IID = InstanceIdentifier.create(Nodes.class);
+ private final DataBroker dataBroker;
+ private final LogicalDatastoreType logicalDatastoreType;
+
+ public FlowCapableNodeOdlDao(DataBroker dataBroker, LogicalDatastoreType logicalDatastoreType) {
+ this.dataBroker = dataBroker;
+ this.logicalDatastoreType = logicalDatastoreType;
+ }
+
+ public Optional<FlowCapableNode> loadByNodeId(@Nonnull NodeId nodeId) {
+ try (final ReadOnlyTransaction roTx = dataBroker.newReadOnlyTransaction()) {
+ final InstanceIdentifier<FlowCapableNode> path =
+ NODES_IID.child(Node.class, new NodeKey(nodeId)).augmentation(FlowCapableNode.class);
+ return roTx.read(logicalDatastoreType, path).checkedGet(5000, TimeUnit.MILLISECONDS);
+ } catch (ReadFailedException | TimeoutException e) {
+ LOG.error("error reading {}", nodeId, e);
+ }
+
+ return Optional.absent();
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.dao;
+
+import com.google.common.base.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+/**
+ * Adding cache to data access object of {@link FlowCapableNode}.
+ */
+public class FlowCapableNodeSnapshotDao implements FlowCapableNodeDao {
+
+ private final ConcurrentHashMap<String, FlowCapableNode> cache = new ConcurrentHashMap<>();
+
+ public void updateCache(@Nonnull NodeId nodeId, Optional<FlowCapableNode> dataAfter) {
+ if (dataAfter.isPresent()) {
+ cache.put(nodeId.getValue(), dataAfter.get());
+ } else {
+ cache.remove(nodeId.getValue());
+ }
+ }
+
+ public Optional<FlowCapableNode> loadByNodeId(@Nonnull NodeId nodeId) {
+ final FlowCapableNode node = cache.get(nodeId.getValue());
+ return Optional.fromNullable(node);
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.NodeListener;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract Listener for node changes.
+ */
+public abstract class AbstractFrmSyncListener<T extends DataObject> implements NodeListener<T> {
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractFrmSyncListener.class);
+
+ @Override
+ public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<T>> modifications) {
+ for (DataTreeModification<T> modification : modifications) {
+ final NodeId nodeId = PathUtil.digNodeId(modification.getRootPath().getRootIdentifier());
+
+ try {
+ final Optional<ListenableFuture<Boolean>> optFuture = processNodeModification(modification);
+ if (optFuture.isPresent()) {
+ final ListenableFuture<Boolean> future = optFuture.get();
+ final Boolean ret = future.get(15000, TimeUnit.MILLISECONDS);
+ LOG.debug("syncup ret {} {} {} thread:{}", dsType(), ret, nodeId.getValue(), threadName());
+ }
+ } catch (InterruptedException e) {
+ LOG.warn("permit for forwarding rules sync not acquired: {}", nodeId.getValue());
+ } catch (Exception e) {
+ LOG.error("error processing inventory node modification: {}", nodeId.getValue(), e);
+ }
+ }
+ }
+
+ protected abstract Optional<ListenableFuture<Boolean>> processNodeModification(
+ DataTreeModification<T> modification) throws InterruptedException;
+
+ protected abstract LogicalDatastoreType dsType();
+
+ private static String threadName() {
+ final Thread currentThread = Thread.currentThread();
+ return currentThread.getName();
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.applications.frsync.ForwardingRulesCommitter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implements {@link ForwardingRulesCommitter} methods for processing add, update and remove of {@link Flow}.
+ */
+public class FlowForwarder implements ForwardingRulesCommitter<Flow, AddFlowOutput, RemoveFlowOutput, UpdateFlowOutput> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FlowForwarder.class);
+ private final SalFlowService salFlowService;
+
+ public FlowForwarder(final SalFlowService salFlowService) {
+ this.salFlowService = salFlowService;
+ }
+
+ @Override
+ public Future<RpcResult<RemoveFlowOutput>> remove(final InstanceIdentifier<Flow> identifier,
+ final Flow removeDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ LOG.trace("Forwarding Flow REMOVE request Tbl id, node Id {} {}",
+ identifier, nodeIdent);
+
+ final TableKey tableKey = identifier.firstKeyOf(Table.class, TableKey.class);
+ if (tableIdValidationPrecondition(tableKey, removeDataObj)) {
+ final RemoveFlowInputBuilder builder = new RemoveFlowInputBuilder(removeDataObj);
+ builder.setFlowRef(new FlowRef(identifier));
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+ builder.setFlowTable(new FlowTableRef(nodeIdent.child(Table.class, tableKey)));
+
+ // always needs to set strict flag into remove-flow input so that
+ // only a flow entry associated with a given flow object will be removed.
+ builder.setStrict(Boolean.TRUE);
+ return salFlowService.removeFlow(builder.build());
+ } else {
+ return RpcResultBuilder.<RemoveFlowOutput>failed()
+ .withError(RpcError.ErrorType.APPLICATION, "tableId mismatch").buildFuture();
+ }
+ }
+
+ @Override
+ public Future<RpcResult<UpdateFlowOutput>> update(final InstanceIdentifier<Flow> identifier,
+ final Flow original, final Flow update,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ LOG.trace("Forwarding Flow UPDATE request [Tbl id, node Id {} {} {}",
+ identifier, nodeIdent, update);
+
+ final Future<RpcResult<UpdateFlowOutput>> output;
+ final TableKey tableKey = identifier.firstKeyOf(Table.class, TableKey.class);
+ if (tableIdValidationPrecondition(tableKey, update)) {
+ final UpdateFlowInputBuilder builder = new UpdateFlowInputBuilder();
+
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+ builder.setFlowRef(new FlowRef(identifier));
+
+ // always needs to set strict flag into update-flow input so that
+ // only a flow entry associated with a given flow object is updated.
+ builder.setUpdatedFlow((new UpdatedFlowBuilder(update)).setStrict(Boolean.TRUE).build());
+ builder.setOriginalFlow((new OriginalFlowBuilder(original)).setStrict(Boolean.TRUE).build());
+
+ output = salFlowService.updateFlow(builder.build());
+ } else {
+ output = RpcResultBuilder.<UpdateFlowOutput>failed()
+ .withError(RpcError.ErrorType.APPLICATION, "tableId mismatch").buildFuture();
+ }
+
+ return output;
+ }
+
+ @Override
+ public Future<RpcResult<AddFlowOutput>> add(final InstanceIdentifier<Flow> identifier,
+ final Flow addDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ LOG.trace("Forwarding the Flow ADD request [Tbl id, node Id {} {} {}",
+ identifier, nodeIdent, addDataObj);
+
+ final Future<RpcResult<AddFlowOutput>> output;
+ final TableKey tableKey = identifier.firstKeyOf(Table.class, TableKey.class);
+ if (tableIdValidationPrecondition(tableKey, addDataObj)) {
+ final AddFlowInputBuilder builder = new AddFlowInputBuilder(addDataObj);
+
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+ builder.setFlowRef(new FlowRef(identifier));
+ builder.setFlowTable(new FlowTableRef(nodeIdent.child(Table.class, tableKey)));
+ output = salFlowService.addFlow(builder.build());
+ } else {
+ output = RpcResultBuilder.<AddFlowOutput>failed().withError(RpcError.ErrorType.APPLICATION, "tableId mismatch").buildFuture();
+ }
+ return output;
+ }
+
+ private static boolean tableIdValidationPrecondition(final TableKey tableKey, final Flow flow) {
+ Preconditions.checkNotNull(tableKey, "TableKey can not be null or empty!");
+ Preconditions.checkNotNull(flow, "Flow can not be null or empty!");
+ if (!tableKey.getId().equals(flow.getTableId())) {
+ LOG.warn("TableID in URI tableId={} and in palyload tableId={} is not same.",
+ flow.getTableId(), tableKey.getId());
+ return false;
+ }
+ return true;
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.concurrent.Callable;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.openflowplugin.applications.frsync.NodeListener;
+import org.opendaylight.openflowplugin.applications.frsync.SyncPlanPushStrategy;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeCachedDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeOdlDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeSnapshotDao;
+import org.opendaylight.openflowplugin.applications.frsync.impl.strategy.SyncPlanPushStrategyFlatBatchImpl;
+import org.opendaylight.openflowplugin.applications.frsync.util.RetryRegistry;
+import org.opendaylight.openflowplugin.applications.frsync.util.SemaphoreKeeperGuavaImpl;
+import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Top provider of forwarding rules synchronization functionality.
+ */
+public class ForwardingRulesSyncProvider implements AutoCloseable, BindingAwareProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ForwardingRulesSyncProvider.class);
+ private static final int STARTUP_LOOP_TICK = 500;
+ private static final int STARTUP_LOOP_MAX_RETRIES = 8;
+
+ private final DataBroker dataService;
+ private final SalTableService salTableService;
+ private final SalFlatBatchService flatBatchService;
+
+ /** Wildcard path to flow-capable-node augmentation of inventory node. */
+ private static final InstanceIdentifier<FlowCapableNode> FLOW_CAPABLE_NODE_WC_PATH =
+ InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
+ /** Wildcard path to node (not flow-capable-node augmentation) of inventory node. */
+ private static final InstanceIdentifier<Node> NODE_WC_PATH =
+ InstanceIdentifier.create(Nodes.class).child(Node.class);
+
+
+ private final DataTreeIdentifier<FlowCapableNode> nodeConfigDataTreePath;
+ private final DataTreeIdentifier<Node> nodeOperationalDataTreePath;
+
+ private ListenerRegistration<NodeListener> dataTreeConfigChangeListener;
+ private ListenerRegistration<NodeListener> dataTreeOperationalChangeListener;
+
+ public ForwardingRulesSyncProvider(final BindingAwareBroker broker,
+ final DataBroker dataBroker,
+ final RpcConsumerRegistry rpcRegistry) {
+ Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
+ this.dataService = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
+ this.salTableService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalTableService.class),
+ "RPC SalTableService not found.");
+ this.flatBatchService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlatBatchService.class),
+ "RPC SalFlatBatchService not found.");
+
+ nodeConfigDataTreePath = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, FLOW_CAPABLE_NODE_WC_PATH);
+ nodeOperationalDataTreePath = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, NODE_WC_PATH);
+
+ broker.registerProvider(this);
+ }
+
+ private final ListeningExecutorService syncThreadPool = FrmExecutors.instance()
+ // TODO improve log in ThreadPoolExecutor.afterExecute
+ // TODO max bloking queue size
+ // TODO core/min pool size
+ .newFixedThreadPool(6, new ThreadFactoryBuilder()
+ .setNameFormat(SyncReactorFutureDecorator.FRM_RPC_CLIENT_PREFIX + "%d")
+ .setDaemon(false)
+ .setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(Thread thread, Throwable e) {
+ LOG.error("uncaught exception {}", thread, e);
+ }
+ })
+ .build());
+
+ @Override
+ public void onSessionInitiated(final BindingAwareBroker.ProviderContext providerContext) {
+ final TableForwarder tableForwarder = new TableForwarder(salTableService);
+
+ final SyncPlanPushStrategy syncPlanPushStrategy = new SyncPlanPushStrategyFlatBatchImpl()
+ .setFlatBatchService(flatBatchService)
+ .setTableForwarder(tableForwarder);
+
+ final RetryRegistry retryRegistry = new RetryRegistry();
+
+ final SyncReactor syncReactorImpl = new SyncReactorImpl(syncPlanPushStrategy);
+ final SyncReactor syncReactorRetry = new SyncReactorRetryDecorator(syncReactorImpl, retryRegistry);
+ final SyncReactor syncReactorGuard = new SyncReactorGuardDecorator(syncReactorRetry,
+ new SemaphoreKeeperGuavaImpl<InstanceIdentifier<FlowCapableNode>>(1, true));
+
+ final SyncReactor reactor = new SyncReactorFutureZipDecorator(syncReactorGuard, syncThreadPool);
+
+ final FlowCapableNodeSnapshotDao configSnapshot = new FlowCapableNodeSnapshotDao();
+ final FlowCapableNodeSnapshotDao operationalSnapshot = new FlowCapableNodeSnapshotDao();
+ final FlowCapableNodeDao configDao = new FlowCapableNodeCachedDao(configSnapshot,
+ new FlowCapableNodeOdlDao(dataService, LogicalDatastoreType.CONFIGURATION));
+ final FlowCapableNodeDao operationalDao = new FlowCapableNodeCachedDao(operationalSnapshot,
+ new FlowCapableNodeOdlDao(dataService, LogicalDatastoreType.OPERATIONAL));
+
+ final NodeListener<FlowCapableNode> nodeListenerConfig =
+ new SimplifiedConfigListener(reactor, configSnapshot, operationalDao);
+ final NodeListener<Node> nodeListenerOperational =
+ new SimplifiedOperationalRetryListener(reactor, operationalSnapshot, configDao, retryRegistry);
+
+ try {
+ SimpleTaskRetryLooper looper1 = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
+ dataTreeConfigChangeListener = looper1.loopUntilNoException(
+ new Callable<ListenerRegistration<NodeListener>>() {
+ @Override
+ public ListenerRegistration<NodeListener> call() throws Exception {
+ return dataService.registerDataTreeChangeListener(
+ nodeConfigDataTreePath, nodeListenerConfig);
+ }
+ });
+
+ SimpleTaskRetryLooper looper2 = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
+ dataTreeOperationalChangeListener = looper2.loopUntilNoException(
+ new Callable<ListenerRegistration<NodeListener>>() {
+ @Override
+ public ListenerRegistration<NodeListener> call() throws Exception {
+ return dataService.registerDataTreeChangeListener(
+ nodeOperationalDataTreePath, nodeListenerOperational);
+ }
+ });
+ } catch (final Exception e) {
+ LOG.warn("FR-Sync node DataChange listener registration fail!", e);
+ throw new IllegalStateException("FR-Sync startup fail!", e);
+ }
+ LOG.info("ForwardingRulesSync has started.");
+ }
+
+ public void close() throws Exception {
+ if (dataTreeConfigChangeListener != null) {
+ dataTreeConfigChangeListener.close();
+ dataTreeConfigChangeListener = null;
+ }
+ if (dataTreeOperationalChangeListener != null) {
+ dataTreeOperationalChangeListener.close();
+ dataTreeOperationalChangeListener = null;
+ }
+
+ syncThreadPool.shutdown();
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Static Factory for creating ExecutorServices (because there is no dependency injection but
+ * static getInstance).
+ */
+public final class FrmExecutors {
+ public static PceExecutorsFactory instance() {
+ return DEFAULT_EXECUTORS;
+ }
+
+ public interface PceExecutorsFactory {
+
+ ListeningExecutorService newFixedThreadPool(int nThreads, ThreadFactory factory);
+ }
+
+ /**
+ * This will be rewritten in JUnits using SynchronousExecutorService.
+ */
+ @VisibleForTesting // should not be private and final
+ static PceExecutorsFactory DEFAULT_EXECUTORS = new PceExecutorsFactory() {
+
+ public ListeningExecutorService newFixedThreadPool(int nThreads, ThreadFactory factory) {
+ final ExecutorService executorService = Executors.newFixedThreadPool(nThreads, factory);
+ return MoreExecutors.listeningDecorator(executorService);
+ }
+ };
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.applications.frsync.ForwardingRulesCommitter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implements {@link ForwardingRulesCommitter} methods for processing add, update and remove of {@link Group}.
+ */
+public class GroupForwarder implements ForwardingRulesCommitter<Group, AddGroupOutput, RemoveGroupOutput, UpdateGroupOutput> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GroupForwarder.class);
+ private final SalGroupService salGroupService;
+
+ public GroupForwarder(SalGroupService salGroupService) {
+ this.salGroupService = salGroupService;
+ }
+
+ @Override
+ public Future<RpcResult<RemoveGroupOutput>> remove(final InstanceIdentifier<Group> identifier, final Group removeDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ LOG.trace("Forwarding Table REMOVE request [Tbl id, node Id {} {}",
+ identifier, nodeIdent);
+
+ final RemoveGroupInputBuilder builder = new RemoveGroupInputBuilder(removeDataObj);
+
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+ builder.setGroupRef(new GroupRef(identifier));
+ // fix group removal - no buckets allowed
+ builder.setBuckets(null);
+ return salGroupService.removeGroup(builder.build());
+ }
+
+ @Override
+ public Future<RpcResult<UpdateGroupOutput>> update(final InstanceIdentifier<Group> identifier,
+ final Group original, final Group update,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ LOG.trace("Forwarding Group UPDATE request [Tbl id, node Id {} {} {}",
+ identifier, nodeIdent, update);
+
+ final UpdateGroupInputBuilder builder = new UpdateGroupInputBuilder();
+
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+ builder.setGroupRef(new GroupRef(identifier));
+ builder.setUpdatedGroup((new UpdatedGroupBuilder(update)).build());
+ builder.setOriginalGroup((new OriginalGroupBuilder(original)).build());
+
+ return salGroupService.updateGroup(builder.build());
+ }
+
+ @Override
+ public Future<RpcResult<AddGroupOutput>> add(final InstanceIdentifier<Group> identifier, final Group addDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ LOG.trace("Forwarding Group ADD request [Tbl id, node Id {} {} {}",
+ identifier, nodeIdent, addDataObj);
+
+ final AddGroupInputBuilder builder = new AddGroupInputBuilder(addDataObj);
+
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+ builder.setGroupRef(new GroupRef(identifier));
+ return salGroupService.addGroup(builder.build());
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.applications.frsync.ForwardingRulesCommitter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutput;
+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.UpdateMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implements {@link ForwardingRulesCommitter} methods for processing add, update and remove of {@link Meter}.
+ */
+public class MeterForwarder implements ForwardingRulesCommitter<Meter, AddMeterOutput, RemoveMeterOutput, UpdateMeterOutput> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MeterForwarder.class);
+ private final SalMeterService salMeterService;
+
+ public MeterForwarder(SalMeterService salMeterService) {
+ this.salMeterService = salMeterService;
+ }
+
+ @Override
+ public Future<RpcResult<RemoveMeterOutput>> remove(final InstanceIdentifier<Meter> identifier, final Meter removeDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+
+ LOG.trace("Received the Meter REMOVE request [Tbl id, node Id {} {}",
+ identifier, nodeIdent);
+
+ final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(removeDataObj);
+
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+ builder.setMeterRef(new MeterRef(identifier));
+ return salMeterService.removeMeter(builder.build());
+ }
+
+ @Override
+ public Future<RpcResult<UpdateMeterOutput>> update(final InstanceIdentifier<Meter> identifier,
+ final Meter original, final Meter update,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ LOG.trace("Received the Meter UPDATE request [Tbl id, node Id {} {} {}",
+ identifier, nodeIdent, update);
+
+ final UpdateMeterInputBuilder builder = new UpdateMeterInputBuilder();
+
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+ builder.setMeterRef(new MeterRef(identifier));
+ builder.setUpdatedMeter((new UpdatedMeterBuilder(update)).build());
+ builder.setOriginalMeter((new OriginalMeterBuilder(original)).build());
+
+ return salMeterService.updateMeter(builder.build());
+ }
+
+ @Override
+ public Future<RpcResult<AddMeterOutput>> add(final InstanceIdentifier<Meter> identifier, final Meter addDataObj,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ LOG.trace("Received the Meter ADD request [Tbl id, node Id {} {} {}",
+ identifier, nodeIdent, addDataObj);
+
+ final AddMeterInputBuilder builder = new AddMeterInputBuilder(addDataObj);
+
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+ builder.setMeterRef(new MeterRef(identifier));
+ return salMeterService.addMeter(builder.build());
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeSnapshotDao;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Listens to config changes and delegates add/remove/update/barrier to {@link SyncReactor}.
+ */
+public class SimplifiedConfigListener extends AbstractFrmSyncListener<FlowCapableNode> {
+ private static final Logger LOG = LoggerFactory.getLogger(SimplifiedConfigListener.class);
+ private final SyncReactor reactor;
+ private final FlowCapableNodeSnapshotDao configSnaphot;
+ private final FlowCapableNodeDao operationalDao;
+
+ public SimplifiedConfigListener(final SyncReactor reactor, FlowCapableNodeSnapshotDao configSnaphot,
+ FlowCapableNodeDao operationalDao) {
+ this.reactor = reactor;
+ this.configSnaphot = configSnaphot;
+ this.operationalDao = operationalDao;
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<FlowCapableNode>> modifications) {
+ LOG.trace("Inventory Config changes {}", modifications.size());
+ super.onDataTreeChanged(modifications);
+ }
+
+ /**
+ * Compare cached operational with current config modification. If operational is not present
+ * skip calling Inventory RPCs.
+ * @throws InterruptedException from syncup
+ */
+ protected Optional<ListenableFuture<Boolean>> processNodeModification(
+ DataTreeModification<FlowCapableNode> modification) throws InterruptedException {
+ final InstanceIdentifier<FlowCapableNode> nodePath = modification.getRootPath().getRootIdentifier();
+ final NodeId nodeId = PathUtil.digNodeId(nodePath);
+
+ configSnaphot.updateCache(nodeId, Optional.fromNullable(modification.getRootNode().getDataAfter()));
+
+
+ final Optional<FlowCapableNode> operationalNode = operationalDao.loadByNodeId(nodeId);
+ if (!operationalNode.isPresent()) {
+ LOG.info("Skip syncup, {} operational is not present", nodeId.getValue());
+ return Optional.absent();
+ }
+
+ final DataObjectModification<FlowCapableNode> configModification = modification.getRootNode();
+ final FlowCapableNode dataBefore = configModification.getDataBefore();
+ final FlowCapableNode dataAfter = configModification.getDataAfter();
+ final ListenableFuture<Boolean> endResult;
+ if (dataBefore == null && dataAfter != null) {
+ endResult = onNodeAdded(nodePath, dataAfter, operationalNode.get());
+ } else if (dataBefore != null && dataAfter == null) {
+ endResult = onNodeDeleted(nodePath, dataBefore);
+ } else {
+ endResult = onNodeUpdated(nodePath, dataBefore, dataAfter);
+ }
+
+ return Optional.of(endResult);
+ }
+
+ /**
+ * Add only what is missing in operational store. Config. node could be added in two situations:
+ * <ul>
+ * <li>Note very first time after restart was handled by operational listener. Syncup should
+ * calculate no delta (we don want to reconfigure switch if not necessary).</li>
+ * <li>But later the config. node could be deleted, after that config node added again. Syncup
+ * should calculate that everything needs to be added. Operational store should be empty in
+ * optimal case (but the switch could be reprogrammed by another person/system.</li>
+ * </ul>
+ */
+ private ListenableFuture<Boolean> onNodeAdded(InstanceIdentifier<FlowCapableNode> nodePath,
+ FlowCapableNode dataAfter, FlowCapableNode operationalNode) throws InterruptedException {
+ NodeId nodeId = PathUtil.digNodeId(nodePath);
+ LOG.trace("onNodeAdded {}", nodeId);
+ final ListenableFuture<Boolean> endResult = reactor.syncup(nodePath, dataAfter, operationalNode, dsType());
+ return endResult;
+ }
+
+ /**
+ * Apply minimal changes very fast. For better performance needed just compare config
+ * after+before. Config listener should not be dependent on operational flows/groups while
+ * updating config because operational store is highly async and it depends on another module in
+ * system which is updating operational store (that components is also trying to solve
+ * scale/performance issues on several layers).
+ */
+ private ListenableFuture<Boolean> onNodeUpdated(InstanceIdentifier<FlowCapableNode> nodePath,
+ FlowCapableNode dataBefore, FlowCapableNode dataAfter) throws InterruptedException {
+ NodeId nodeId = PathUtil.digNodeId(nodePath);
+ LOG.trace("onNodeUpdated {}", nodeId);
+ final ListenableFuture<Boolean> endResult = reactor.syncup(nodePath, dataAfter, dataBefore, dsType());
+ return endResult;
+ }
+
+ /**
+ * Remove values that are being deleted in the config from the switch. Note, this could be
+ * probably optimized using dedicated wipe-out RPC, but it has impact on switch if it is
+ * programmed by two person/system
+ */
+ private ListenableFuture<Boolean> onNodeDeleted(InstanceIdentifier<FlowCapableNode> nodePath,
+ FlowCapableNode dataBefore) throws InterruptedException {
+ NodeId nodeId = PathUtil.digNodeId(nodePath);
+ LOG.trace("onNodeDeleted {}", nodeId);
+ final ListenableFuture<Boolean> endResult = reactor.syncup(nodePath, null, dataBefore, dsType());
+ return endResult;
+ }
+
+ @Override
+ public LogicalDatastoreType dsType() {
+ return LogicalDatastoreType.CONFIGURATION;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeSnapshotDao;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Listens to operational new nodes and delegates add/remove/update/barrier to {@link SyncReactor}.
+ */
+public class SimplifiedOperationalListener extends AbstractFrmSyncListener<Node> {
+ private static final Logger LOG = LoggerFactory.getLogger(SimplifiedOperationalListener.class);
+
+ private final SyncReactor reactor;
+ private final FlowCapableNodeSnapshotDao operationalSnapshot;
+ private final FlowCapableNodeDao configDao;
+
+ public SimplifiedOperationalListener(SyncReactor reactor, FlowCapableNodeSnapshotDao operationalSnapshot,
+ FlowCapableNodeDao configDao) {
+ this.reactor = reactor;
+ this.operationalSnapshot = operationalSnapshot;
+ this.configDao = configDao;
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<Node>> modifications) {
+ LOG.trace("Inventory Operational changes {}", modifications.size());
+ super.onDataTreeChanged(modifications);
+ }
+
+ /**
+ * This method behaves like this:
+ * <ul>
+ * <li>If node is added to operational store then reconciliation.</li>
+ * <li>Node is deleted from operational cache is removed.</li>
+ * <li>Skip this event otherwise.</li>
+ * </ul>
+ *
+ * @throws InterruptedException from syncup
+ */
+ protected Optional<ListenableFuture<Boolean>> processNodeModification(
+ DataTreeModification<Node> modification) throws InterruptedException {
+
+ updateCache(modification);
+ if (isReconciliationNeeded(modification)) {
+ return reconciliation(modification);
+ }
+ return skipModification(modification);
+ }
+
+ /**
+ * Remove if delete. Update only if FlowCapableNode Augmentation modified.
+ *
+ * @param modification Datastore modification
+ * @return true for cache update, false for cache remove
+ */
+ protected boolean updateCache(DataTreeModification<Node> modification) {
+ if (isDelete(modification) || isDeleteLogical(modification)) {
+ operationalSnapshot.updateCache(nodeId(modification), Optional.<FlowCapableNode>absent());
+ return false;
+ }
+ operationalSnapshot.updateCache(nodeId(modification), Optional.fromNullable(flowCapableNodeAfter(modification)));
+ return true;
+ }
+
+ private Optional<ListenableFuture<Boolean>> skipModification(DataTreeModification<Node> modification) {
+ LOG.trace("Skipping Inventory Operational modification {}, before {}, after {}", nodeIdValue(modification),
+ modification.getRootNode().getDataBefore() == null ? "null" : "nonnull",
+ modification.getRootNode().getDataAfter() == null ? "null" : "nonnull");
+ return Optional.absent();
+ }
+
+ /**
+ * ModificationType.DELETE.
+ */
+ private boolean isDelete(DataTreeModification<Node> modification) {
+ if (ModificationType.DELETE == modification.getRootNode().getModificationType()) {
+ LOG.trace("Delete {} (physical)", nodeIdValue(modification));
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * All connectors disappeared from operational store (logical delete).
+ */
+ private boolean isDeleteLogical(DataTreeModification<Node> modification) {
+ final DataObjectModification<Node> rootNode = modification.getRootNode();
+ if (!safeConnectorsEmpty(rootNode.getDataBefore()) && safeConnectorsEmpty(rootNode.getDataAfter())) {
+ LOG.trace("Delete {} (logical)", nodeIdValue(modification));
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isAdd(DataTreeModification<Node> modification) {
+ final DataObjectModification<Node> rootNode = modification.getRootNode();
+ final Node dataAfter = rootNode.getDataAfter();
+ final Node dataBefore = rootNode.getDataBefore();
+
+ final boolean nodeAppearedInOperational = dataBefore == null && dataAfter != null;
+ if (nodeAppearedInOperational) {
+ LOG.trace("Add {} (physical)", nodeIdValue(modification));
+ }
+ return nodeAppearedInOperational;
+ }
+
+ /**
+ * All connectors appeared in operational store (logical add).
+ */
+ private boolean isAddLogical(DataTreeModification<Node> modification) {
+ final DataObjectModification<Node> rootNode = modification.getRootNode();
+ if (safeConnectorsEmpty(rootNode.getDataBefore()) && !safeConnectorsEmpty(rootNode.getDataAfter())) {
+ LOG.trace("Add {} (logical)", nodeIdValue(modification));
+ return true;
+ }
+
+ return false;
+ }
+
+ protected boolean isReconciliationNeeded(DataTreeModification<Node> modification) {
+ return isAdd(modification) || isAddLogical(modification);
+ }
+
+ private Optional<ListenableFuture<Boolean>> reconciliation(DataTreeModification<Node> modification) throws InterruptedException {
+ final NodeId nodeId = nodeId(modification);
+ final Optional<FlowCapableNode> nodeConfiguration = configDao.loadByNodeId(nodeId);
+
+ if (nodeConfiguration.isPresent()) {
+ LOG.debug("Reconciliation: {}", nodeId.getValue());
+ final InstanceIdentifier<FlowCapableNode> nodePath = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, new NodeKey(nodeId(modification))).augmentation(FlowCapableNode.class);
+ return Optional.of(reactor.syncup(nodePath, nodeConfiguration.get(), flowCapableNodeAfter(modification), dsType()));
+ } else {
+ return skipModification(modification);
+ }
+ }
+
+ private static FlowCapableNode flowCapableNodeAfter(DataTreeModification<Node> modification) {
+ final Node dataAfter = modification.getRootNode().getDataAfter();
+ if (dataAfter == null) {
+ return null;
+ }
+ return dataAfter.getAugmentation(FlowCapableNode.class);
+ }
+
+ private static boolean safeConnectorsEmpty(Node node) {
+ if (node == null) {
+ return true;
+ }
+
+ final List<NodeConnector> nodeConnectors = node.getNodeConnector();
+
+ return nodeConnectors == null || nodeConnectors.isEmpty();
+ }
+
+ private static String nodeIdValue(DataTreeModification<Node> modification) {
+ final NodeId nodeId = nodeId(modification);
+
+ if (nodeId == null) {
+ return null;
+ }
+
+ return nodeId.getValue();
+ }
+
+ static NodeId nodeId(DataTreeModification<Node> modification) {
+ final DataObjectModification<Node> rootNode = modification.getRootNode();
+ final Node dataAfter = rootNode.getDataAfter();
+
+ if (dataAfter != null) {
+ return dataAfter.getId();
+ }
+
+ final Node dataBefore = rootNode.getDataBefore();
+ if (dataBefore != null) {
+ return dataBefore.getId();
+ }
+
+ return null;
+ }
+
+ @Override
+ public LogicalDatastoreType dsType() {
+ return LogicalDatastoreType.OPERATIONAL;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeSnapshotDao;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.RetryRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableStatisticsGatheringStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.snapshot.gathering.status.grouping.SnapshotGatheringStatusEnd;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Modified {@link SimplifiedOperationalListener} for usage of retry mechanism.
+ */
+public class SimplifiedOperationalRetryListener extends SimplifiedOperationalListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SimplifiedOperationalRetryListener.class);
+ private final RetryRegistry retryRegistry;
+
+ public SimplifiedOperationalRetryListener(SyncReactor reactor, FlowCapableNodeSnapshotDao operationalSnapshot,
+ FlowCapableNodeDao configDao, RetryRegistry retryRegistry) {
+ super(reactor, operationalSnapshot, configDao);
+ this.retryRegistry = retryRegistry;
+ }
+
+ /**
+ * Adding condition check for retry.
+ *
+ * @param modification operational datastore modification
+ * @return true if reconciliation is needed, false otherwise
+ */
+ protected boolean isReconciliationNeeded(DataTreeModification<Node> modification) {
+ return super.isReconciliationNeeded(modification) || isRegisteredAndConsistentForRetry(modification);
+ }
+
+ /**
+ * If node is removed unregister for retry in addition.
+ *
+ * @param modification operational datastore modification
+ * @return true for cache update, false for cache remove and retry unregister
+ */
+ protected boolean updateCache(DataTreeModification<Node> modification) {
+ boolean nodeUpdated = super.updateCache(modification);
+ if (!nodeUpdated) { // node removed if not updated
+ retryRegistry.unregisterIfRegistered(nodeId(modification));
+ }
+ return nodeUpdated;
+ }
+
+ /**
+ * Check if retry should be proceeded.
+ *
+ * @param modification operational modification
+ * @return true if device is registered for retry and actual modification is consistent, false otherwise
+ */
+ private boolean isRegisteredAndConsistentForRetry(DataTreeModification<Node> modification) {
+ final NodeId nodeId = PathUtil.digNodeId(modification.getRootPath().getRootIdentifier());
+
+ if (!retryRegistry.isRegistered(nodeId)) {
+ return false;
+ }
+
+ final FlowCapableStatisticsGatheringStatus gatheringStatus = modification.getRootNode().getDataAfter()
+ .getAugmentation(FlowCapableStatisticsGatheringStatus.class);
+
+ if (gatheringStatus == null) {
+ LOG.trace("Statistics gathering never started for: {}", nodeId.getValue());
+ return false;
+ }
+
+ final SnapshotGatheringStatusEnd gatheringStatusEnd = gatheringStatus.getSnapshotGatheringStatusEnd();
+
+ if (gatheringStatusEnd == null) {
+ LOG.trace("Statistics gathering is not over yet for: {}", nodeId.getValue());
+ return false;
+ }
+
+ if (!gatheringStatusEnd.isSucceeded()) {
+ LOG.debug("Statistics gathering was not successful for: {}", nodeId.getValue());
+ return false;
+ }
+
+ try {
+ Date timestampOfRegistration = retryRegistry.getRegistration(nodeId);
+ final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(RetryRegistry.DATE_AND_TIME_FORMAT);
+ Date timestampOfStatistics = simpleDateFormat.parse(gatheringStatusEnd.getEnd().getValue());
+ if (timestampOfStatistics.after(timestampOfRegistration)) {
+ LOG.debug("Fresh operational present for: {} -> going retry!", nodeId.getValue());
+ return true;
+ }
+ } catch (ParseException e) {
+ LOG.error("Timestamp parsing error {}", e);
+ }
+ LOG.debug("Fresh operational not present for: {}", nodeId.getValue());
+ return false;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Decorator for running delegate syncup in Future.
+ */
+public class SyncReactorFutureDecorator implements SyncReactor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncReactorFutureDecorator.class);
+ public static final String FRM_RPC_CLIENT_PREFIX = "FRM-RPC-client-";
+ private final SyncReactor delegate;
+ private final ListeningExecutorService executorService;
+
+ public SyncReactorFutureDecorator(SyncReactor delegate, ListeningExecutorService executorService) {
+ this.delegate = delegate;
+ this.executorService = executorService;
+ }
+
+ public ListenableFuture<Boolean> syncup(final InstanceIdentifier<FlowCapableNode> flowcapableNodePath,
+ final FlowCapableNode configTree, final FlowCapableNode operationalTree,
+ final LogicalDatastoreType dsType) throws InterruptedException {
+ final NodeId nodeId = PathUtil.digNodeId(flowcapableNodePath);
+ LOG.trace("syncup future {}", nodeId.getValue());
+
+ final ListenableFuture<Boolean> syncup = executorService.submit(new Callable<Boolean>() {
+ public Boolean call() throws Exception {
+ final String oldThreadName = updateThreadName(nodeId);
+
+ try {
+ final Boolean ret = doSyncupInFuture(flowcapableNodePath, configTree, operationalTree, dsType)
+ .get(10000, TimeUnit.MILLISECONDS);
+ LOG.trace("ret {} {}", nodeId.getValue(), ret);
+ return true;
+ } catch (TimeoutException e) {
+ LOG.error("doSyncupInFuture timeout occured {}", nodeId.getValue(), e);
+ return false;
+ } finally {
+ updateThreadName(oldThreadName);
+ }
+ }
+ });
+
+ return syncup;
+ }
+
+ protected ListenableFuture<Boolean> doSyncupInFuture(final InstanceIdentifier<FlowCapableNode> flowcapableNodePath,
+ final FlowCapableNode configTree, final FlowCapableNode operationalTree,
+ final LogicalDatastoreType dsType) throws InterruptedException {
+ final NodeId nodeId = PathUtil.digNodeId(flowcapableNodePath);
+ LOG.trace("doSyncupInFuture future {}", nodeId.getValue());
+
+ return delegate.syncup(flowcapableNodePath, configTree, operationalTree, dsType);
+ }
+
+ private String updateThreadName(NodeId nodeId) {
+ final Thread currentThread = Thread.currentThread();
+ final String oldName = currentThread.getName();
+ try {
+ if (oldName.startsWith(SyncReactorFutureDecorator.FRM_RPC_CLIENT_PREFIX)) {
+ currentThread.setName(oldName + "@" + nodeId.getValue());
+ } else {
+ LOG.warn("try to update foreign thread name {} {}", nodeId, oldName);
+ }
+ } catch (Exception e) {
+ LOG.error("failed updating threadName {}", nodeId, e);
+ }
+ return oldName;
+ }
+
+ private String updateThreadName(String name) {
+ final Thread currentThread = Thread.currentThread();
+ final String oldName = currentThread.getName();
+ try {
+ if (oldName.startsWith(SyncReactorFutureDecorator.FRM_RPC_CLIENT_PREFIX)) {
+ currentThread.setName(name);
+ } else {
+ LOG.warn("try to update foreign thread name {} {}", oldName, name);
+ }
+ } catch (Exception e) {
+ LOG.error("failed updating threadName {}", name, e);
+ }
+ return oldName;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Semaphore;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.ZipQueueEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Enriches {@link SyncReactorFutureDecorator} with state compression.
+ */
+public class SyncReactorFutureZipDecorator extends SyncReactorFutureDecorator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncReactorFutureZipDecorator.class);
+
+ @GuardedBy("compressionGuard")
+ private final Map<InstanceIdentifier<FlowCapableNode>, ZipQueueEntry> compressionQueue = new HashMap<>();
+ private final Semaphore compressionGuard = new Semaphore(1, false);
+
+ public SyncReactorFutureZipDecorator(SyncReactor delegate, ListeningExecutorService executorService) {
+ super(delegate, executorService);
+ }
+
+ public ListenableFuture<Boolean> syncup(final InstanceIdentifier<FlowCapableNode> flowcapableNodePath,
+ final FlowCapableNode configTree, final FlowCapableNode operationalTree,
+ final LogicalDatastoreType dsType) throws InterruptedException {
+ final NodeId nodeId = PathUtil.digNodeId(flowcapableNodePath);
+ LOG.trace("syncup zip {}", nodeId.getValue());
+
+ try {
+ compressionGuard.acquire();
+
+ final boolean newFutureNecessary = updateCompressionState(flowcapableNodePath, configTree, operationalTree, dsType);
+ if (newFutureNecessary) {
+ super.syncup(flowcapableNodePath, configTree, operationalTree, dsType);
+ }
+ return Futures.immediateFuture(true);
+ } finally {
+ compressionGuard.release();
+ }
+ }
+
+ protected ListenableFuture<Boolean> doSyncupInFuture(final InstanceIdentifier<FlowCapableNode> flowcapableNodePath,
+ final FlowCapableNode configTree, final FlowCapableNode operationalTree,
+ final LogicalDatastoreType dsType) throws InterruptedException {
+ final NodeId nodeId = PathUtil.digNodeId(flowcapableNodePath);
+ LOG.trace("doSyncupInFuture zip {}", nodeId.getValue());
+
+ final ZipQueueEntry lastCompressionState = removeLastCompressionState(flowcapableNodePath);
+ if (lastCompressionState == null) {
+ return Futures.immediateFuture(true);
+ } else {
+ return super.doSyncupInFuture(flowcapableNodePath,
+ lastCompressionState.getLeft(), lastCompressionState.getRight(), dsType);
+ }
+ }
+
+ /**
+ * If there is config delta in compression queue for the device and new configuration is coming,
+ * update its zip queue entry. Create/replace zip queue entry for the device with operational delta otherwise.
+ */
+ private boolean updateCompressionState(final InstanceIdentifier<FlowCapableNode> flowcapableNodePath,
+ final FlowCapableNode configTree, final FlowCapableNode operationalTree,
+ final LogicalDatastoreType dsType) {
+ final ZipQueueEntry previousEntry = compressionQueue.get(flowcapableNodePath);
+
+ if (previousEntry != null && dsType == LogicalDatastoreType.CONFIGURATION
+ && previousEntry.getDsType() == LogicalDatastoreType.CONFIGURATION) {
+ putOptimizedConfigDelta(flowcapableNodePath, configTree, previousEntry);
+ } else {
+ putLatestOperationalDelta(flowcapableNodePath, configTree, operationalTree, dsType);
+ }
+ return previousEntry == null;
+ }
+
+ private void putOptimizedConfigDelta(InstanceIdentifier<FlowCapableNode> flowcapableNodePath, FlowCapableNode configTree,
+ ZipQueueEntry previous) {
+ compressionQueue.put(flowcapableNodePath, new ZipQueueEntry(configTree, previous.getRight(), previous.getDsType()));
+ }
+
+ private void putLatestOperationalDelta(InstanceIdentifier<FlowCapableNode> flowcapableNodePath, FlowCapableNode configTree,
+ FlowCapableNode operationalTree, LogicalDatastoreType dsType) {
+ compressionQueue.put(flowcapableNodePath, new ZipQueueEntry(configTree, operationalTree, dsType));
+ }
+
+ private ZipQueueEntry removeLastCompressionState(
+ final InstanceIdentifier<FlowCapableNode> flowcapableNodePath) {
+ try {
+ try {
+ compressionGuard.acquire();
+ } catch (InterruptedException e) {
+ return null;
+ }
+
+ return compressionQueue.remove(flowcapableNodePath);
+ } finally {
+ compressionGuard.release();
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SemaphoreKeeper;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Decorator for NodeId level syncup locking.
+ */
+public class SyncReactorGuardDecorator implements SyncReactor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncReactorGuardDecorator.class);
+
+ private final SyncReactor delegate;
+ private final SemaphoreKeeper<InstanceIdentifier<FlowCapableNode>> semaphoreKeeper;
+
+ public SyncReactorGuardDecorator(SyncReactor delegate,
+ SemaphoreKeeper<InstanceIdentifier<FlowCapableNode>> semaphoreKeeper) {
+ this.delegate = delegate;
+ this.semaphoreKeeper = semaphoreKeeper;
+ }
+
+ public ListenableFuture<Boolean> syncup(final InstanceIdentifier<FlowCapableNode> flowcapableNodePath,
+ final FlowCapableNode configTree, final FlowCapableNode operationalTree,
+ final LogicalDatastoreType dsType) throws InterruptedException {
+ final NodeId nodeId = PathUtil.digNodeId(flowcapableNodePath);
+ LOG.trace("syncup guard {}", nodeId.getValue());
+
+ final long stampBeforeGuard = System.nanoTime();
+ final Semaphore guard = summonGuardAndAcquire(flowcapableNodePath);//TODO handle InteruptedException
+
+ try {
+ final long stampAfterGuard = System.nanoTime();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("syncup start {} waiting:{} guard:{} thread:{}", nodeId.getValue(),
+ formatNanos(stampAfterGuard - stampBeforeGuard),
+ guard, threadName());
+ }
+
+ final ListenableFuture<Boolean> endResult =
+ delegate.syncup(flowcapableNodePath, configTree, operationalTree, dsType);//TODO handle InteruptedException
+
+ Futures.addCallback(endResult, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(@Nullable final Boolean result) {
+ if (LOG.isDebugEnabled()) {
+ final long stampFinished = System.nanoTime();
+ LOG.debug("syncup finished {} took:{} rpc:{} wait:{} guard:{} permits thread:{}", nodeId.getValue(),
+ formatNanos(stampFinished - stampBeforeGuard),
+ formatNanos(stampFinished - stampAfterGuard),
+ formatNanos(stampAfterGuard - stampBeforeGuard),
+ guard.availablePermits(), threadName());
+ }
+
+ releaseGuardForNodeId(guard);
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ if (LOG.isDebugEnabled()) {
+ final long stampFinished = System.nanoTime();
+ LOG.warn("syncup failed {} took:{} rpc:{} wait:{} guard:{} permits thread:{}", nodeId.getValue(),
+ formatNanos(stampFinished - stampBeforeGuard),
+ formatNanos(stampFinished - stampAfterGuard),
+ formatNanos(stampAfterGuard - stampBeforeGuard),
+ guard.availablePermits(), threadName());
+ }
+
+ releaseGuardForNodeId(guard);
+ }
+ });
+ return endResult;
+ } catch(InterruptedException e) {
+ releaseGuardForNodeId(guard);
+ throw e;
+ }
+ }
+
+ private String formatNanos(long nanos) {
+ return "'" + TimeUnit.NANOSECONDS.toMillis(nanos) + " ms'";
+ }
+
+ /**
+ * Get guard and lock for node.
+ * @param flowcapableNodePath II of node for which guard should be acquired
+ * @return semaphore guard
+ */
+ private Semaphore summonGuardAndAcquire(final InstanceIdentifier<FlowCapableNode> flowcapableNodePath)
+ throws InterruptedException {
+ final Semaphore guard = Preconditions.checkNotNull(semaphoreKeeper.summonGuard(flowcapableNodePath),
+ "no guard for " + flowcapableNodePath);
+
+ if (LOG.isDebugEnabled()) {
+ final NodeId nodeId = PathUtil.digNodeId(flowcapableNodePath);
+ try {
+ LOG.debug("syncup summon {} guard:{} thread:{}", nodeId.getValue(), guard, threadName());
+ } catch (Exception e) {
+ LOG.error("error logging guard after summon before aquiring {}", nodeId);
+ }
+ }
+
+ guard.acquire();
+ return guard;
+ }
+
+ /**
+ * Unlock and release guard.
+ * @param guard semaphore guard which should be unlocked
+ */
+ private void releaseGuardForNodeId(final Semaphore guard) {
+ if (guard == null) {
+ return;
+ }
+ guard.release();
+ }
+
+ private static String threadName() {
+ final Thread currentThread = Thread.currentThread();
+ return currentThread.getName();
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncPlanPushStrategy;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.impl.strategy.SynchronizationDiffInput;
+import org.opendaylight.openflowplugin.applications.frsync.util.CrudCounts;
+import org.opendaylight.openflowplugin.applications.frsync.util.FlowCapableNodeLookups;
+import org.opendaylight.openflowplugin.applications.frsync.util.FxChainUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.ItemSyncBox;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.ReconcileUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.SyncCrudCounters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Synchronization reactor implementation, applicable for both - syncup and reconciliation.
+ */
+public class SyncReactorImpl implements SyncReactor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncReactorImpl.class);
+ private final SyncPlanPushStrategy syncPlanPushStrategy;
+
+ public SyncReactorImpl(SyncPlanPushStrategy syncPlanPushStrategy) {
+ this.syncPlanPushStrategy = Preconditions.checkNotNull(syncPlanPushStrategy, "execution strategy is mandatory");
+ }
+
+ @Override
+ public ListenableFuture<Boolean> syncup(final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final FlowCapableNode configTree, final FlowCapableNode operationalTree,
+ final LogicalDatastoreType dsType) {
+
+ final NodeId nodeId = PathUtil.digNodeId(nodeIdent);
+ LOG.trace("syncup impl {} cfg:{} oper:{}", nodeId.getValue(), configTree == null ? "is null" : "non null", operationalTree == null ? "is null" : "non null");
+ final SyncCrudCounters counters = new SyncCrudCounters();
+
+ /**
+ * instructions:
+ * - extract diff changes and prepare change steps in safe order
+ * - optimization: decide if updates needed
+ * - execute chosen implementation (e.g. conventional API, bulk API, flat bulk API)
+ * - recommended order follows:
+ * reconciliation strategy - phase 1: - add/update missing objects in following order:
+ * - table features - groups (reordered) - meters - flows
+ *
+ * reconciliation strategy - phase 2: - remove redundant objects in following order:
+ * - flows - meters - groups (reordered)
+ **/
+
+ final List<ItemSyncBox<Group>> groupsToAddOrUpdate = extractGroupsToAddOrUpdate(nodeId, configTree, operationalTree);
+ final ItemSyncBox<Meter> metersToAddOrUpdate = extractMetersToAddOrUpdate(nodeId, configTree, operationalTree);
+ final Map<TableKey, ItemSyncBox<Flow>> flowsToAddOrUpdate = extractFlowsToAddOrUpdate(nodeId, configTree, operationalTree);
+
+ final Map<TableKey, ItemSyncBox<Flow>> flowsToRemove = extractFlowsToRemove(nodeId, configTree, operationalTree);
+ final ItemSyncBox<Meter> metersToRemove = extractMetersToRemove(nodeId, configTree, operationalTree);
+ final List<ItemSyncBox<Group>> groupsToRemove = extractGroupsToRemove(nodeId, configTree, operationalTree);
+
+ final SynchronizationDiffInput input = new SynchronizationDiffInput(nodeIdent,
+ groupsToAddOrUpdate, metersToAddOrUpdate, flowsToAddOrUpdate,
+ flowsToRemove, metersToRemove, groupsToRemove);
+
+ counters.setStartNano(System.nanoTime());
+ final ListenableFuture<RpcResult<Void>> bootstrapResultFuture = RpcResultBuilder.<Void>success().buildFuture();
+ final ListenableFuture<RpcResult<Void>> resultVehicle = syncPlanPushStrategy.executeSyncStrategy(
+ bootstrapResultFuture, input, counters);
+
+ // log final result
+ Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "final result"));
+
+ return Futures.transform(resultVehicle, new Function<RpcResult<Void>, Boolean>() {
+ @Override
+ public Boolean apply(RpcResult<Void> input) {
+ if (input == null) {
+ return false;
+ }
+
+ if (LOG.isDebugEnabled()) {
+ final CrudCounts flowCrudCounts = counters.getFlowCrudCounts();
+ final CrudCounts meterCrudCounts = counters.getMeterCrudCounts();
+ final CrudCounts groupCrudCounts = counters.getGroupCrudCounts();
+ LOG.debug("sync-outcome[{}] (added/updated/removed): flow={}/{}/{}, meter={}/{}/{}, group={}/{}/{}, took={} ms",
+ nodeId.getValue(),
+ flowCrudCounts.getAdded(),
+ flowCrudCounts.getUpdated(),
+ flowCrudCounts.getRemoved(),
+ meterCrudCounts.getAdded(),
+ meterCrudCounts.getUpdated(),
+ meterCrudCounts.getRemoved(),
+ groupCrudCounts.getAdded(),
+ groupCrudCounts.getUpdated(),
+ groupCrudCounts.getRemoved(),
+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - counters.getStartNano())
+ );
+ }
+
+ LOG.trace("syncup errors: {}", input.getErrors());
+ return input.isSuccessful();
+ }
+ });
+ }
+
+ @VisibleForTesting
+ private static List<ItemSyncBox<Group>> extractGroupsToAddOrUpdate(final NodeId nodeId,
+ final FlowCapableNode flowCapableNodeConfigured,
+ final FlowCapableNode flowCapableNodeOperational) {
+ final List<Group> groupsConfigured = ReconcileUtil.safeGroups(flowCapableNodeConfigured);
+ final List<Group> groupsOperational = ReconcileUtil.safeGroups(flowCapableNodeOperational);
+ final Map<Long, Group> groupOperationalMap = FlowCapableNodeLookups.wrapGroupsToMap(groupsOperational);
+
+ final List<Group> pendingGroups = new ArrayList<>();
+ pendingGroups.addAll(groupsConfigured);
+
+ return ReconcileUtil.resolveAndDivideGroupDiffs(nodeId, groupOperationalMap, pendingGroups, true);
+ }
+
+ @VisibleForTesting
+ private static ItemSyncBox<Meter> extractMetersToAddOrUpdate(final NodeId nodeId,
+ final FlowCapableNode flowCapableNodeConfigured,
+ final FlowCapableNode flowCapableNodeOperational) {
+ final List<Meter> metersConfigured = ReconcileUtil.safeMeters(flowCapableNodeConfigured);
+ final List<Meter> metersOperational = ReconcileUtil.safeMeters(flowCapableNodeOperational);
+ final Map<MeterId, Meter> meterOperationalMap = FlowCapableNodeLookups.wrapMetersToMap(metersOperational);
+
+ return ReconcileUtil.resolveMeterDiffs(nodeId, meterOperationalMap, metersConfigured, true);
+ }
+
+ @VisibleForTesting
+ private static Map<TableKey, ItemSyncBox<Flow>> extractFlowsToAddOrUpdate(final NodeId nodeId,
+ final FlowCapableNode flowCapableNodeConfigured,
+ final FlowCapableNode flowCapableNodeOperational) {
+ final List<Table> tablesConfigured = ReconcileUtil.safeTables(flowCapableNodeConfigured);
+ if (tablesConfigured.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ final List<Table> tablesOperational = ReconcileUtil.safeTables(flowCapableNodeOperational);
+ final Map<Short, Table> tableOperationalMap = FlowCapableNodeLookups.wrapTablesToMap(tablesOperational);
+
+ return ReconcileUtil.resolveFlowDiffsInAllTables(nodeId, tableOperationalMap, tablesConfigured, true);
+ }
+
+ @VisibleForTesting
+ private static Map<TableKey, ItemSyncBox<Flow>> extractFlowsToRemove(final NodeId nodeId,
+ final FlowCapableNode flowCapableNodeConfigured,
+ final FlowCapableNode flowCapableNodeOperational) {
+ final List<Table> tablesOperational = ReconcileUtil.safeTables(flowCapableNodeOperational);
+ if (tablesOperational.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ final List<Table> tablesConfigured = ReconcileUtil.safeTables(flowCapableNodeConfigured);
+ final Map<Short, Table> tableConfiguredMap = FlowCapableNodeLookups.wrapTablesToMap(tablesConfigured);
+
+ return ReconcileUtil.resolveFlowDiffsInAllTables(nodeId, tableConfiguredMap, tablesOperational, false);
+ }
+
+ @VisibleForTesting
+ private static ItemSyncBox<Meter> extractMetersToRemove(final NodeId nodeId,
+ final FlowCapableNode flowCapableNodeConfigured,
+ final FlowCapableNode flowCapableNodeOperational) {
+ final List<Meter> metersConfigured = ReconcileUtil.safeMeters(flowCapableNodeConfigured);
+ final List<Meter> metersOperational = ReconcileUtil.safeMeters(flowCapableNodeOperational);
+ final Map<MeterId, Meter> meterConfiguredMap = FlowCapableNodeLookups.wrapMetersToMap(metersConfigured);
+
+ return ReconcileUtil.resolveMeterDiffs(nodeId, meterConfiguredMap, metersOperational, false);
+ }
+
+ @VisibleForTesting
+ private static List<ItemSyncBox<Group>> extractGroupsToRemove(final NodeId nodeId,
+ final FlowCapableNode flowCapableNodeConfigured,
+ final FlowCapableNode flowCapableNodeOperational) {
+ final List<Group> groupsConfigured = ReconcileUtil.safeGroups(flowCapableNodeConfigured);
+ final List<Group> groupsOperational = ReconcileUtil.safeGroups(flowCapableNodeOperational);
+ final Map<Long, Group> groupConfiguredMap = FlowCapableNodeLookups.wrapGroupsToMap(groupsConfigured);
+
+ final List<Group> pendingGroups = new ArrayList<>();
+ pendingGroups.addAll(groupsOperational);
+
+ return ReconcileUtil.resolveAndDivideGroupDiffs(nodeId, groupConfiguredMap, pendingGroups, false);
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.RetryRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Adding retry mechanism in case of unsuccessful syncup.
+ */
+public class SyncReactorRetryDecorator implements SyncReactor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncReactorRetryDecorator.class);
+
+ private final SyncReactor delegate;
+ private final RetryRegistry retryRegistry;
+
+ public SyncReactorRetryDecorator(final SyncReactor delegate, RetryRegistry retryRegistry) {
+ this.delegate = delegate;
+ this.retryRegistry = retryRegistry;
+ }
+
+ public ListenableFuture<Boolean> syncup(final InstanceIdentifier<FlowCapableNode> flowcapableNodePath,
+ final FlowCapableNode configTree, final FlowCapableNode operationalTree,
+ final LogicalDatastoreType dsType) throws InterruptedException {
+
+ final NodeId nodeId = PathUtil.digNodeId(flowcapableNodePath);
+ LOG.trace("syncup retry {}", nodeId.getValue());
+
+ if (dsType == LogicalDatastoreType.CONFIGURATION && retryRegistry.isRegistered(nodeId)) {
+ LOG.trace("Config change ignored because device is in retry [{}]", nodeId);
+ return Futures.immediateFuture(Boolean.FALSE);
+ }
+
+ ListenableFuture<Boolean> syncupResult = delegate.syncup(flowcapableNodePath, configTree, operationalTree, dsType);
+
+ return Futures.transform(syncupResult, new Function<Boolean, Boolean>() {
+ @Override
+ public Boolean apply(Boolean result) {
+ LOG.trace("syncup ret in retry {}", result);
+ if (result) {
+ retryRegistry.unregisterIfRegistered(nodeId);
+ return true;
+ } else {
+ retryRegistry.register(nodeId);
+ // TODO elicit statistics gathering if not running actually
+ // triggerStatisticsGathering(nodeId);
+ return false;
+ }
+ }
+ });
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import java.util.Collections;
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.applications.frsync.ForwardingRulesUpdateCommitter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.table.update.OriginalTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.table.update.UpdatedTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implements {@link ForwardingRulesUpdateCommitter} methods for processing update of {@link TableFeatures}.
+ */
+public class TableForwarder implements ForwardingRulesUpdateCommitter<TableFeatures, UpdateTableOutput> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TableForwarder.class);
+ private final SalTableService salTableService;
+
+ public TableForwarder(SalTableService salTableService) {
+ this.salTableService = salTableService;
+ }
+
+ @Override
+ public Future<RpcResult<UpdateTableOutput>> update(final InstanceIdentifier<TableFeatures> identifier,
+ final TableFeatures original, final TableFeatures update,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ LOG.debug("Forwarding Table Update request [Tbl id, node Id {} {}",
+ identifier, nodeIdent);
+
+ final UpdateTableInputBuilder builder = new UpdateTableInputBuilder();
+
+ builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
+
+ final InstanceIdentifier<Table> iiToTable = nodeIdent.child(Table.class,
+ new TableKey(identifier.firstKeyOf(TableFeatures.class).getTableId()));
+ builder.setTableRef(new TableRef(iiToTable));
+
+ builder.setUpdatedTable(new UpdatedTableBuilder().setTableFeatures(
+ Collections.singletonList(update)).build());
+
+ builder.setOriginalTable(new OriginalTableBuilder().setTableFeatures(
+ Collections.singletonList(original)).build());
+ LOG.debug("Invoking SalTableService {} ", nodeIdent);
+
+ return salTableService.updateTable(builder.build());
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl.strategy;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.PeekingIterator;
+import com.google.common.collect.Range;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Future;
+import javax.annotation.Nullable;
+import org.opendaylight.openflowplugin.applications.frsync.SyncPlanPushStrategy;
+import org.opendaylight.openflowplugin.applications.frsync.impl.TableForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.util.FxChainUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.ItemSyncBox;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.ReconcileUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.SyncCrudCounters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.Batch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.BatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.BatchChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddFlowCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddMeterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveFlowCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveMeterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateFlowCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateMeterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.flow._case.FlatBatchAddFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.flow._case.FlatBatchAddFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.group._case.FlatBatchAddGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.group._case.FlatBatchAddGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.meter._case.FlatBatchAddMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.meter._case.FlatBatchAddMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.flow._case.FlatBatchRemoveFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.flow._case.FlatBatchRemoveFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.group._case.FlatBatchRemoveGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.group._case.FlatBatchRemoveGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.meter._case.FlatBatchRemoveMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.meter._case.FlatBatchRemoveMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.flow._case.FlatBatchUpdateFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.flow._case.FlatBatchUpdateFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.group._case.FlatBatchUpdateGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.group._case.FlatBatchUpdateGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.meter._case.FlatBatchUpdateMeter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.meter._case.FlatBatchUpdateMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailure;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.batch.flow.input.update.grouping.OriginalBatchedFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.batch.flow.input.update.grouping.UpdatedBatchedFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.batch.group.input.update.grouping.OriginalBatchedGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.batch.group.input.update.grouping.UpdatedBatchedGroupBuilder;
+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.meters.service.rev160316.batch.meter.input.update.grouping.OriginalBatchedMeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.batch.meter.input.update.grouping.UpdatedBatchedMeterBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Execute CRUD API for flow + group + meter involving flat-batch strategy.
+ */
+public class SyncPlanPushStrategyFlatBatchImpl implements SyncPlanPushStrategy {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncPlanPushStrategyFlatBatchImpl.class);
+
+ private SalFlatBatchService flatBatchService;
+ private TableForwarder tableForwarder;
+
+ @Override
+ public ListenableFuture<RpcResult<Void>> executeSyncStrategy(ListenableFuture<RpcResult<Void>> resultVehicle,
+ final SynchronizationDiffInput diffInput,
+ final SyncCrudCounters counters) {
+ final InstanceIdentifier<FlowCapableNode> nodeIdent = diffInput.getNodeIdent();
+ final NodeId nodeId = PathUtil.digNodeId(nodeIdent);
+
+ // prepare default (full) counts
+ counters.getGroupCrudCounts().setAdded(ReconcileUtil.countTotalPushed(diffInput.getGroupsToAddOrUpdate()));
+ counters.getGroupCrudCounts().setUpdated(ReconcileUtil.countTotalUpdated(diffInput.getGroupsToAddOrUpdate()));
+ counters.getGroupCrudCounts().setRemoved(ReconcileUtil.countTotalPushed(diffInput.getGroupsToRemove()));
+
+ counters.getFlowCrudCounts().setAdded(ReconcileUtil.countTotalPushed(diffInput.getFlowsToAddOrUpdate().values()));
+ counters.getFlowCrudCounts().setUpdated(ReconcileUtil.countTotalUpdated(diffInput.getFlowsToAddOrUpdate().values()));
+ counters.getFlowCrudCounts().setRemoved(ReconcileUtil.countTotalPushed(diffInput.getFlowsToRemove().values()));
+
+ counters.getMeterCrudCounts().setAdded(diffInput.getMetersToAddOrUpdate().getItemsToPush().size());
+ counters.getMeterCrudCounts().setUpdated(diffInput.getMetersToAddOrUpdate().getItemsToUpdate().size());
+ counters.getMeterCrudCounts().setRemoved(diffInput.getMetersToRemove().getItemsToPush().size());
+
+ /* Tables - have to be pushed before groups */
+ // TODO enable table-update when ready
+ //resultVehicle = updateTableFeatures(nodeIdent, configTree);
+
+ resultVehicle = Futures.transform(resultVehicle, new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input) throws Exception {
+ if (!input.isSuccessful()) {
+ //TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
+ //final ListenableFuture<RpcResult<Void>> singleVoidUpdateResult = Futures.transform(
+ // Futures.asList Arrays.asList(input, output),
+ // ReconcileUtil.<UpdateFlowOutput>createRpcResultCondenser("TODO"));
+ }
+
+ final List<Batch> batchBag = new ArrayList<>();
+ int batchOrder = 0;
+
+ batchOrder = assembleAddOrUpdateGroups(batchBag, batchOrder, diffInput.getGroupsToAddOrUpdate());
+ batchOrder = assembleAddOrUpdateMeters(batchBag, batchOrder, diffInput.getMetersToAddOrUpdate());
+ batchOrder = assembleAddOrUpdateFlows(batchBag, batchOrder, diffInput.getFlowsToAddOrUpdate());
+
+ batchOrder = assembleRemoveFlows(batchBag, batchOrder, diffInput.getFlowsToRemove());
+ batchOrder = assembleRemoveMeters(batchBag, batchOrder, diffInput.getMetersToRemove());
+ batchOrder = assembleRemoveGroups(batchBag, batchOrder, diffInput.getGroupsToRemove());
+
+ LOG.trace("Index of last batch step: {}", batchOrder);
+
+ final ProcessFlatBatchInput flatBatchInput = new ProcessFlatBatchInputBuilder()
+ .setNode(new NodeRef(PathUtil.digNodePath(diffInput.getNodeIdent())))
+ .setExitOnFirstError(false) // TODO: propagate from input
+ .setBatch(batchBag)
+ .build();
+
+ final Future<RpcResult<ProcessFlatBatchOutput>> rpcResultFuture = flatBatchService.processFlatBatch(flatBatchInput);
+
+ final int failureIndexLimit = batchOrder;
+
+ if (LOG.isDebugEnabled()) {
+ Futures.addCallback(JdkFutureAdapters.listenInPoolThread(rpcResultFuture),
+ createCounterCallback(batchBag, failureIndexLimit, counters));
+ }
+
+ return Futures.transform(JdkFutureAdapters.listenInPoolThread(rpcResultFuture),
+ ReconcileUtil.<ProcessFlatBatchOutput>createRpcResultToVoidFunction("flat-batch"));
+ }
+ });
+
+ Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "flat-batch"));
+ return resultVehicle;
+ }
+
+ private FutureCallback<RpcResult<ProcessFlatBatchOutput>> createCounterCallback(final List<Batch> inputBatchBag,
+ final int failureIndexLimit,
+ final SyncCrudCounters counters) {
+ return new FutureCallback<RpcResult<ProcessFlatBatchOutput>>() {
+ @Override
+ public void onSuccess(@Nullable final RpcResult<ProcessFlatBatchOutput> result) {
+ if (!result.isSuccessful() && result.getResult() != null && !result.getResult().getBatchFailure().isEmpty()) {
+ Map<Range<Integer>, Batch> batchMap = mapBatchesToRanges(inputBatchBag, failureIndexLimit);
+
+ for (BatchFailure batchFailure : result.getResult().getBatchFailure()) {
+ for (Map.Entry<Range<Integer>, Batch> rangeBatchEntry : batchMap.entrySet()) {
+ if (rangeBatchEntry.getKey().contains(batchFailure.getBatchOrder())) {
+ // get type and decrease
+ final BatchChoice batchChoice = rangeBatchEntry.getValue().getBatchChoice();
+ decrementCounters(batchChoice, counters);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ counters.resetAll();
+ }
+ };
+ }
+
+ static void decrementCounters(final BatchChoice batchChoice, final SyncCrudCounters counters) {
+ if (batchChoice instanceof FlatBatchAddFlowCase) {
+ counters.getFlowCrudCounts().decAdded();
+ } else if (batchChoice instanceof FlatBatchUpdateFlowCase) {
+ counters.getFlowCrudCounts().decUpdated();
+ } else if (batchChoice instanceof FlatBatchRemoveFlowCase) {
+ counters.getFlowCrudCounts().decRemoved();
+ } else if (batchChoice instanceof FlatBatchAddGroupCase) {
+ counters.getGroupCrudCounts().decAdded();
+ } else if (batchChoice instanceof FlatBatchUpdateGroupCase) {
+ counters.getGroupCrudCounts().decUpdated();
+ } else if (batchChoice instanceof FlatBatchRemoveGroupCase) {
+ counters.getGroupCrudCounts().decRemoved();
+ } else if (batchChoice instanceof FlatBatchAddMeterCase) {
+ counters.getMeterCrudCounts().decAdded();
+ } else if (batchChoice instanceof FlatBatchUpdateMeterCase) {
+ counters.getMeterCrudCounts().decUpdated();
+ } else if (batchChoice instanceof FlatBatchRemoveMeterCase) {
+ counters.getMeterCrudCounts().decRemoved();
+ }
+ }
+
+ static Map<Range<Integer>, Batch> mapBatchesToRanges(final List<Batch> inputBatchBag, final int failureIndexLimit) {
+ final Map<Range<Integer>, Batch> batchMap = new LinkedHashMap<>();
+ final PeekingIterator<Batch> batchPeekingIterator = Iterators.peekingIterator(inputBatchBag.iterator());
+ while (batchPeekingIterator.hasNext()) {
+ final Batch batch = batchPeekingIterator.next();
+ final int nextBatchOrder = batchPeekingIterator.hasNext()
+ ? batchPeekingIterator.peek().getBatchOrder()
+ : failureIndexLimit;
+ batchMap.put(Range.closed(batch.getBatchOrder(), nextBatchOrder - 1), batch);
+ }
+ return batchMap;
+ }
+
+ private int getNextBatchLimit(final PeekingIterator<Batch> inputBatchIterator, final int failureIndexLimit) {
+ return inputBatchIterator.hasNext()
+ ? inputBatchIterator.peek().getBatchOrder()
+ : failureIndexLimit;
+ }
+
+ @VisibleForTesting
+ static int assembleRemoveFlows(final List<Batch> batchBag, int batchOrder, final Map<TableKey, ItemSyncBox<Flow>> flowItemSyncTableMap) {
+ // process flow remove
+ if (flowItemSyncTableMap != null) {
+ for (Map.Entry<TableKey, ItemSyncBox<Flow>> syncBoxEntry : flowItemSyncTableMap.entrySet()) {
+ final ItemSyncBox<Flow> flowItemSyncBox = syncBoxEntry.getValue();
+
+ if (!flowItemSyncBox.getItemsToPush().isEmpty()) {
+ final List<FlatBatchRemoveFlow> flatBatchRemoveFlowBag =
+ new ArrayList<>(flowItemSyncBox.getItemsToUpdate().size());
+ int itemOrder = 0;
+ for (Flow flow : flowItemSyncBox.getItemsToPush()) {
+ flatBatchRemoveFlowBag.add(new FlatBatchRemoveFlowBuilder(flow)
+ .setBatchOrder(itemOrder++)
+ .setFlowId(flow.getId())
+ .build());
+ }
+ final Batch batch = new BatchBuilder()
+ .setBatchChoice(new FlatBatchRemoveFlowCaseBuilder()
+ .setFlatBatchRemoveFlow(flatBatchRemoveFlowBag)
+ .build())
+ .setBatchOrder(batchOrder)
+ .build();
+ batchOrder += itemOrder;
+ batchBag.add(batch);
+ }
+ }
+ }
+ return batchOrder;
+ }
+
+ @VisibleForTesting
+ static int assembleAddOrUpdateGroups(final List<Batch> batchBag, int batchOrder, final List<ItemSyncBox<Group>> groupsToAddOrUpdate) {
+ // process group add+update
+ if (groupsToAddOrUpdate != null) {
+ for (ItemSyncBox<Group> groupItemSyncBox : groupsToAddOrUpdate) {
+ if (!groupItemSyncBox.getItemsToPush().isEmpty()) {
+ final List<FlatBatchAddGroup> flatBatchAddGroupBag =
+ new ArrayList<>(groupItemSyncBox.getItemsToUpdate().size());
+ int itemOrder = 0;
+ for (Group group : groupItemSyncBox.getItemsToPush()) {
+ flatBatchAddGroupBag.add(new FlatBatchAddGroupBuilder(group).setBatchOrder(itemOrder++).build());
+ }
+ final Batch batch = new BatchBuilder()
+ .setBatchChoice(new FlatBatchAddGroupCaseBuilder()
+ .setFlatBatchAddGroup(flatBatchAddGroupBag)
+ .build())
+ .setBatchOrder(batchOrder)
+ .build();
+ batchOrder += itemOrder;
+ batchBag.add(batch);
+ }
+
+ if (!groupItemSyncBox.getItemsToUpdate().isEmpty()) {
+ final List<FlatBatchUpdateGroup> flatBatchUpdateGroupBag =
+ new ArrayList<>(groupItemSyncBox.getItemsToUpdate().size());
+ int itemOrder = 0;
+ for (ItemSyncBox.ItemUpdateTuple<Group> groupUpdate : groupItemSyncBox.getItemsToUpdate()) {
+ flatBatchUpdateGroupBag.add(new FlatBatchUpdateGroupBuilder()
+ .setBatchOrder(itemOrder++)
+ .setOriginalBatchedGroup(new OriginalBatchedGroupBuilder(groupUpdate.getOriginal()).build())
+ .setUpdatedBatchedGroup(new UpdatedBatchedGroupBuilder(groupUpdate.getUpdated()).build())
+ .build());
+ }
+ final Batch batch = new BatchBuilder()
+ .setBatchChoice(new FlatBatchUpdateGroupCaseBuilder()
+ .setFlatBatchUpdateGroup(flatBatchUpdateGroupBag)
+ .build())
+ .setBatchOrder(batchOrder)
+ .build();
+ batchOrder += itemOrder;
+ batchBag.add(batch);
+ }
+ }
+ }
+ return batchOrder;
+ }
+
+ @VisibleForTesting
+ static int assembleRemoveGroups(final List<Batch> batchBag, int batchOrder, final List<ItemSyncBox<Group>> groupsToRemoveOrUpdate) {
+ // process group add+update
+ if (groupsToRemoveOrUpdate != null) {
+ for (ItemSyncBox<Group> groupItemSyncBox : groupsToRemoveOrUpdate) {
+ if (!groupItemSyncBox.getItemsToPush().isEmpty()) {
+ final List<FlatBatchRemoveGroup> flatBatchRemoveGroupBag =
+ new ArrayList<>(groupItemSyncBox.getItemsToUpdate().size());
+ int itemOrder = 0;
+ for (Group group : groupItemSyncBox.getItemsToPush()) {
+ flatBatchRemoveGroupBag.add(new FlatBatchRemoveGroupBuilder(group).setBatchOrder(itemOrder++).build());
+ }
+ final Batch batch = new BatchBuilder()
+ .setBatchChoice(new FlatBatchRemoveGroupCaseBuilder()
+ .setFlatBatchRemoveGroup(flatBatchRemoveGroupBag)
+ .build())
+ .setBatchOrder(batchOrder)
+ .build();
+ batchOrder += itemOrder;
+ batchBag.add(batch);
+ }
+ }
+ }
+ return batchOrder;
+ }
+
+ @VisibleForTesting
+ static int assembleAddOrUpdateMeters(final List<Batch> batchBag, int batchOrder, final ItemSyncBox<Meter> meterItemSyncBox) {
+ // process meter add+update
+ if (meterItemSyncBox != null) {
+ if (!meterItemSyncBox.getItemsToPush().isEmpty()) {
+ final List<FlatBatchAddMeter> flatBatchAddMeterBag =
+ new ArrayList<>(meterItemSyncBox.getItemsToUpdate().size());
+ int itemOrder = 0;
+ for (Meter meter : meterItemSyncBox.getItemsToPush()) {
+ flatBatchAddMeterBag.add(new FlatBatchAddMeterBuilder(meter).setBatchOrder(itemOrder++).build());
+ }
+ final Batch batch = new BatchBuilder()
+ .setBatchChoice(new FlatBatchAddMeterCaseBuilder()
+ .setFlatBatchAddMeter(flatBatchAddMeterBag)
+ .build())
+ .setBatchOrder(batchOrder)
+ .build();
+ batchOrder += itemOrder;
+ batchBag.add(batch);
+ }
+
+ if (!meterItemSyncBox.getItemsToUpdate().isEmpty()) {
+ final List<FlatBatchUpdateMeter> flatBatchUpdateMeterBag =
+ new ArrayList<>(meterItemSyncBox.getItemsToUpdate().size());
+ int itemOrder = 0;
+ for (ItemSyncBox.ItemUpdateTuple<Meter> meterUpdate : meterItemSyncBox.getItemsToUpdate()) {
+ flatBatchUpdateMeterBag.add(new FlatBatchUpdateMeterBuilder()
+ .setBatchOrder(itemOrder++)
+ .setOriginalBatchedMeter(new OriginalBatchedMeterBuilder(meterUpdate.getOriginal()).build())
+ .setUpdatedBatchedMeter(new UpdatedBatchedMeterBuilder(meterUpdate.getUpdated()).build())
+ .build());
+ }
+ final Batch batch = new BatchBuilder()
+ .setBatchChoice(new FlatBatchUpdateMeterCaseBuilder()
+ .setFlatBatchUpdateMeter(flatBatchUpdateMeterBag)
+ .build())
+ .setBatchOrder(batchOrder)
+ .build();
+ batchOrder += itemOrder;
+ batchBag.add(batch);
+ }
+ }
+ return batchOrder;
+ }
+
+ @VisibleForTesting
+ static int assembleRemoveMeters(final List<Batch> batchBag, int batchOrder, final ItemSyncBox<Meter> meterItemSyncBox) {
+ // process meter remove
+ if (meterItemSyncBox != null) {
+ if (!meterItemSyncBox.getItemsToPush().isEmpty()) {
+ final List<FlatBatchRemoveMeter> flatBatchRemoveMeterBag =
+ new ArrayList<>(meterItemSyncBox.getItemsToUpdate().size());
+ int itemOrder = 0;
+ for (Meter meter : meterItemSyncBox.getItemsToPush()) {
+ flatBatchRemoveMeterBag.add(new FlatBatchRemoveMeterBuilder(meter).setBatchOrder(itemOrder++).build());
+ }
+ final Batch batch = new BatchBuilder()
+ .setBatchChoice(new FlatBatchRemoveMeterCaseBuilder()
+ .setFlatBatchRemoveMeter(flatBatchRemoveMeterBag)
+ .build())
+ .setBatchOrder(batchOrder)
+ .build();
+ batchOrder += itemOrder;
+ batchBag.add(batch);
+ }
+ }
+ return batchOrder;
+ }
+
+ @VisibleForTesting
+ static int assembleAddOrUpdateFlows(final List<Batch> batchBag, int batchOrder, final Map<TableKey, ItemSyncBox<Flow>> flowItemSyncTableMap) {
+ // process flow add+update
+ if (flowItemSyncTableMap != null) {
+ for (Map.Entry<TableKey, ItemSyncBox<Flow>> syncBoxEntry : flowItemSyncTableMap.entrySet()) {
+ final ItemSyncBox<Flow> flowItemSyncBox = syncBoxEntry.getValue();
+
+ if (!flowItemSyncBox.getItemsToPush().isEmpty()) {
+ final List<FlatBatchAddFlow> flatBatchAddFlowBag =
+ new ArrayList<>(flowItemSyncBox.getItemsToUpdate().size());
+ int itemOrder = 0;
+ for (Flow flow : flowItemSyncBox.getItemsToPush()) {
+ flatBatchAddFlowBag.add(new FlatBatchAddFlowBuilder(flow)
+ .setBatchOrder(itemOrder++)
+ .setFlowId(flow.getId())
+ .build());
+ }
+ final Batch batch = new BatchBuilder()
+ .setBatchChoice(new FlatBatchAddFlowCaseBuilder()
+ .setFlatBatchAddFlow(flatBatchAddFlowBag)
+ .build())
+ .setBatchOrder(batchOrder)
+ .build();
+ batchOrder += itemOrder;
+ batchBag.add(batch);
+ }
+
+ if (!flowItemSyncBox.getItemsToUpdate().isEmpty()) {
+ final List<FlatBatchUpdateFlow> flatBatchUpdateFlowBag =
+ new ArrayList<>(flowItemSyncBox.getItemsToUpdate().size());
+ int itemOrder = 0;
+ for (ItemSyncBox.ItemUpdateTuple<Flow> flowUpdate : flowItemSyncBox.getItemsToUpdate()) {
+ flatBatchUpdateFlowBag.add(new FlatBatchUpdateFlowBuilder()
+ .setBatchOrder(itemOrder++)
+ .setFlowId(flowUpdate.getUpdated().getId())
+ .setOriginalBatchedFlow(new OriginalBatchedFlowBuilder(flowUpdate.getOriginal()).build())
+ .setUpdatedBatchedFlow(new UpdatedBatchedFlowBuilder(flowUpdate.getUpdated()).build())
+ .build());
+ }
+ final Batch batch = new BatchBuilder()
+ .setBatchChoice(new FlatBatchUpdateFlowCaseBuilder()
+ .setFlatBatchUpdateFlow(flatBatchUpdateFlowBag)
+ .build())
+ .setBatchOrder(batchOrder)
+ .build();
+ batchOrder += itemOrder;
+ batchBag.add(batch);
+ }
+ }
+ }
+ return batchOrder;
+ }
+
+ public SyncPlanPushStrategyFlatBatchImpl setFlatBatchService(final SalFlatBatchService flatBatchService) {
+ this.flatBatchService = flatBatchService;
+ return this;
+ }
+
+ public SyncPlanPushStrategyFlatBatchImpl setTableForwarder(final TableForwarder tableForwarder) {
+ this.tableForwarder = tableForwarder;
+ return this;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl.strategy;
+
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.openflowplugin.applications.frsync.SyncPlanPushStrategy;
+import org.opendaylight.openflowplugin.applications.frsync.impl.FlowForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.impl.GroupForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.impl.MeterForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.impl.TableForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.util.CrudCounts;
+import org.opendaylight.openflowplugin.applications.frsync.util.FxChainUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.ItemSyncBox;
+import org.opendaylight.openflowplugin.applications.frsync.util.PathUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.ReconcileUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.SyncCrudCounters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Execute CRUD API for flow + group + meter involving one-by-one (incremental) strategy.
+ */
+public class SyncPlanPushStrategyIncrementalImpl implements SyncPlanPushStrategy {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncPlanPushStrategyIncrementalImpl.class);
+
+ private FlowForwarder flowForwarder;
+ private TableForwarder tableForwarder;
+ private MeterForwarder meterForwarder;
+ private GroupForwarder groupForwarder;
+ private FlowCapableTransactionService transactionService;
+
+ @Override
+ public ListenableFuture<RpcResult<Void>> executeSyncStrategy(ListenableFuture<RpcResult<Void>> resultVehicle,
+ final SynchronizationDiffInput diffInput,
+ final SyncCrudCounters counters) {
+ final InstanceIdentifier<FlowCapableNode> nodeIdent = diffInput.getNodeIdent();
+ final NodeId nodeId = PathUtil.digNodeId(nodeIdent);
+
+ /* Tables - have to be pushed before groups */
+ // TODO enable table-update when ready
+ //resultVehicle = updateTableFeatures(nodeIdent, configTree);
+
+ resultVehicle = Futures.transform(resultVehicle, new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input) throws Exception {
+ if (!input.isSuccessful()) {
+ //TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
+ //final ListenableFuture<RpcResult<Void>> singleVoidUpdateResult = Futures.transform(
+ // Futures.asList Arrays.asList(input, output),
+ // ReconcileUtil.<UpdateFlowOutput>createRpcResultCondenser("TODO"));
+ }
+ return addMissingGroups(nodeId, nodeIdent, diffInput.getGroupsToAddOrUpdate(), counters);
+ }
+ });
+ Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "addMissingGroups"));
+ resultVehicle = Futures.transform(resultVehicle, new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input) throws Exception {
+ if (!input.isSuccessful()) {
+ //TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
+ }
+ return addMissingMeters(nodeId, nodeIdent, diffInput.getMetersToAddOrUpdate(), counters);
+ }
+ });
+ Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "addMissingMeters"));
+ resultVehicle = Futures.transform(resultVehicle, new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input) throws Exception {
+ if (!input.isSuccessful()) {
+ //TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
+ }
+ return addMissingFlows(nodeId, nodeIdent, diffInput.getFlowsToAddOrUpdate(), counters);
+ }
+ });
+ Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "addMissingFlows"));
+
+
+ resultVehicle = Futures.transform(resultVehicle, new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input) throws Exception {
+ if (!input.isSuccessful()) {
+ //TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
+ }
+ return removeRedundantFlows(nodeId, nodeIdent, diffInput.getFlowsToRemove(), counters);
+ }
+ });
+ Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "removeRedundantFlows"));
+ resultVehicle = Futures.transform(resultVehicle, new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input) throws Exception {
+ if (!input.isSuccessful()) {
+ //TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
+ }
+ return removeRedundantMeters(nodeId, nodeIdent, diffInput.getMetersToRemove(), counters);
+ }
+ });
+ Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "removeRedundantMeters"));
+ resultVehicle = Futures.transform(resultVehicle, new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input) throws Exception {
+ if (!input.isSuccessful()) {
+ //TODO chain errors but not skip processing on first error return Futures.immediateFuture(input);
+ }
+ return removeRedundantGroups(nodeId, nodeIdent, diffInput.getGroupsToRemove(), counters);
+ }
+ });
+ Futures.addCallback(resultVehicle, FxChainUtil.logResultCallback(nodeId, "removeRedundantGroups"));
+ return resultVehicle;
+ }
+
+
+ ListenableFuture<RpcResult<Void>> addMissingFlows(final NodeId nodeId,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final Map<TableKey, ItemSyncBox<Flow>> flowsInTablesSyncBox,
+ final SyncCrudCounters counters) {
+ if (flowsInTablesSyncBox.isEmpty()) {
+ LOG.trace("no tables in config for node: {} -> SKIPPING", nodeId.getValue());
+ return RpcResultBuilder.<Void>success().buildFuture();
+ }
+
+ final List<ListenableFuture<RpcResult<AddFlowOutput>>> allResults = new ArrayList<>();
+ final List<ListenableFuture<RpcResult<UpdateFlowOutput>>> allUpdateResults = new ArrayList<>();
+ final CrudCounts flowCrudCounts = counters.getFlowCrudCounts();
+
+ for (Map.Entry<TableKey, ItemSyncBox<Flow>> flowsInTableBoxEntry : flowsInTablesSyncBox.entrySet()) {
+ final TableKey tableKey = flowsInTableBoxEntry.getKey();
+ final ItemSyncBox<Flow> flowSyncBox = flowsInTableBoxEntry.getValue();
+
+ final KeyedInstanceIdentifier<Table, TableKey> tableIdent = nodeIdent.child(Table.class, tableKey);
+
+ for (final Flow flow : flowSyncBox.getItemsToPush()) {
+ final KeyedInstanceIdentifier<Flow, FlowKey> flowIdent = tableIdent.child(Flow.class, flow.getKey());
+
+ LOG.trace("adding flow {} in table {} - absent on device {} match{}",
+ flow.getId(), tableKey, nodeId, flow.getMatch());
+
+ allResults.add(JdkFutureAdapters.listenInPoolThread(
+ flowForwarder.add(flowIdent, flow, nodeIdent)));
+ flowCrudCounts.incAdded();
+ }
+
+ for (final ItemSyncBox.ItemUpdateTuple<Flow> flowUpdate : flowSyncBox.getItemsToUpdate()) {
+ final Flow existingFlow = flowUpdate.getOriginal();
+ final Flow updatedFlow = flowUpdate.getUpdated();
+
+ final KeyedInstanceIdentifier<Flow, FlowKey> flowIdent = tableIdent.child(Flow.class, updatedFlow.getKey());
+ LOG.trace("flow {} in table {} - needs update on device {} match{}",
+ updatedFlow.getId(), tableKey, nodeId, updatedFlow.getMatch());
+
+ allUpdateResults.add(JdkFutureAdapters.listenInPoolThread(
+ flowForwarder.update(flowIdent, existingFlow, updatedFlow, nodeIdent)));
+ flowCrudCounts.incUpdated();
+ }
+ }
+
+ final ListenableFuture<RpcResult<Void>> singleVoidAddResult = Futures.transform(
+ Futures.allAsList(allResults),
+ ReconcileUtil.<AddFlowOutput>createRpcResultCondenser("flow adding"));
+
+ final ListenableFuture<RpcResult<Void>> singleVoidUpdateResult = Futures.transform(
+ Futures.allAsList(allUpdateResults),
+ ReconcileUtil.<UpdateFlowOutput>createRpcResultCondenser("flow updating"));
+
+ final ListenableFuture<RpcResult<Void>> summaryResult = Futures.transform(
+ Futures.allAsList(singleVoidAddResult, singleVoidUpdateResult),
+ ReconcileUtil.<Void>createRpcResultCondenser("flow add/update"));
+
+ return summaryResult;
+
+ /*
+ return Futures.transform(summaryResult,
+ ReconcileUtil.chainBarrierFlush(PathUtil.digNodePath(nodeIdent), transactionService));
+ */
+ }
+
+ ListenableFuture<RpcResult<Void>> removeRedundantFlows(final NodeId nodeId,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final Map<TableKey, ItemSyncBox<Flow>> removalPlan,
+ final SyncCrudCounters counters) {
+ if (removalPlan.isEmpty()) {
+ LOG.trace("no tables in operational for node: {} -> SKIPPING", nodeId.getValue());
+ return RpcResultBuilder.<Void>success().buildFuture();
+ }
+
+ final List<ListenableFuture<RpcResult<RemoveFlowOutput>>> allResults = new ArrayList<>();
+ final CrudCounts flowCrudCounts = counters.getFlowCrudCounts();
+
+ for (final Map.Entry<TableKey, ItemSyncBox<Flow>> flowsPerTable : removalPlan.entrySet()) {
+ final KeyedInstanceIdentifier<Table, TableKey> tableIdent =
+ nodeIdent.child(Table.class, flowsPerTable.getKey());
+
+ // loop flows on device and check if the are configured
+ for (final Flow flow : flowsPerTable.getValue().getItemsToPush()) {
+ final KeyedInstanceIdentifier<Flow, FlowKey> flowIdent =
+ tableIdent.child(Flow.class, flow.getKey());
+ allResults.add(JdkFutureAdapters.listenInPoolThread(
+ flowForwarder.remove(flowIdent, flow, nodeIdent)));
+ flowCrudCounts.incRemoved();
+ }
+ }
+
+ final ListenableFuture<RpcResult<Void>> singleVoidResult = Futures.transform(
+ Futures.allAsList(allResults), ReconcileUtil.<RemoveFlowOutput>createRpcResultCondenser("flow remove"));
+ return Futures.transform(singleVoidResult,
+ ReconcileUtil.chainBarrierFlush(PathUtil.digNodePath(nodeIdent), transactionService));
+
+ }
+
+ ListenableFuture<RpcResult<Void>> removeRedundantMeters(final NodeId nodeId,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final ItemSyncBox<Meter> meterRemovalPlan,
+ final SyncCrudCounters counters) {
+ if (meterRemovalPlan.isEmpty()) {
+ LOG.trace("no meters on device for node: {} -> SKIPPING", nodeId.getValue());
+ return RpcResultBuilder.<Void>success().buildFuture();
+ }
+
+ final CrudCounts meterCrudCounts = counters.getMeterCrudCounts();
+
+ final List<ListenableFuture<RpcResult<RemoveMeterOutput>>> allResults = new ArrayList<>();
+ for (Meter meter : meterRemovalPlan.getItemsToPush()) {
+ LOG.trace("removing meter {} - absent in config {}",
+ meter.getMeterId(), nodeId);
+ final KeyedInstanceIdentifier<Meter, MeterKey> meterIdent =
+ nodeIdent.child(Meter.class, meter.getKey());
+ allResults.add(JdkFutureAdapters.listenInPoolThread(
+ meterForwarder.remove(meterIdent, meter, nodeIdent)));
+ meterCrudCounts.incRemoved();
+ }
+
+ final ListenableFuture<RpcResult<Void>> singleVoidResult = Futures.transform(
+ Futures.allAsList(allResults),
+ ReconcileUtil.<RemoveMeterOutput>createRpcResultCondenser("meter remove"));
+ return singleVoidResult;
+ /*
+ return Futures.transform(singleVoidResult,
+ ReconcileUtil.chainBarrierFlush(PathUtil.digNodePath(nodeIdent), transactionService));
+ */
+ }
+
+ ListenableFuture<RpcResult<Void>> removeRedundantGroups(final NodeId nodeId,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final List<ItemSyncBox<Group>> groupsRemovalPlan,
+ final SyncCrudCounters counters) {
+ if (groupsRemovalPlan.isEmpty()) {
+ LOG.trace("no groups on device for node: {} -> SKIPPING", nodeId.getValue());
+ return RpcResultBuilder.<Void>success().buildFuture();
+ }
+
+ final CrudCounts groupCrudCounts = counters.getGroupCrudCounts();
+
+ ListenableFuture<RpcResult<Void>> chainedResult = RpcResultBuilder.<Void>success().buildFuture();
+ try {
+ groupCrudCounts.setRemoved(ReconcileUtil.countTotalPushed(groupsRemovalPlan));
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("removing groups: planSteps={}, toRemoveTotal={}",
+ groupsRemovalPlan.size(), groupCrudCounts.getRemoved());
+ }
+ Collections.reverse(groupsRemovalPlan);
+ for (final ItemSyncBox<Group> groupsPortion : groupsRemovalPlan) {
+ chainedResult =
+ Futures.transform(chainedResult, new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input)
+ throws Exception {
+ final ListenableFuture<RpcResult<Void>> result;
+ if (input.isSuccessful()) {
+ result = flushRemoveGroupPortionAndBarrier(nodeIdent, groupsPortion);
+ } else {
+ // pass through original unsuccessful rpcResult
+ result = Futures.immediateFuture(input);
+ }
+
+ return result;
+ }
+ });
+ }
+ } catch (IllegalStateException e) {
+ chainedResult = RpcResultBuilder.<Void>failed()
+ .withError(RpcError.ErrorType.APPLICATION, "failed to add missing groups", e)
+ .buildFuture();
+ }
+
+ return chainedResult;
+ }
+
+ private ListenableFuture<RpcResult<Void>> flushRemoveGroupPortionAndBarrier(
+ final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final ItemSyncBox<Group> groupsPortion) {
+ List<ListenableFuture<RpcResult<RemoveGroupOutput>>> allResults = new ArrayList<>();
+ for (Group group : groupsPortion.getItemsToPush()) {
+ final KeyedInstanceIdentifier<Group, GroupKey> groupIdent = nodeIdent.child(Group.class, group.getKey());
+ allResults.add(JdkFutureAdapters.listenInPoolThread(groupForwarder.remove(groupIdent, group, nodeIdent)));
+ }
+
+ final ListenableFuture<RpcResult<Void>> singleVoidResult = Futures.transform(
+ Futures.allAsList(allResults),
+ ReconcileUtil.<RemoveGroupOutput>createRpcResultCondenser("group remove"));
+
+ return Futures.transform(singleVoidResult,
+ ReconcileUtil.chainBarrierFlush(PathUtil.digNodePath(nodeIdent), transactionService));
+ }
+
+ ListenableFuture<RpcResult<Void>> updateTableFeatures(final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final FlowCapableNode flowCapableNodeConfigured) {
+ // CHECK if while pushing the update, updateTableInput can be null to emulate a table add
+ final List<Table> tableList = ReconcileUtil.safeTables(flowCapableNodeConfigured);
+
+ final List<ListenableFuture<RpcResult<UpdateTableOutput>>> allResults = new ArrayList<>();
+ for (Table table : tableList) {
+ TableKey tableKey = table.getKey();
+ KeyedInstanceIdentifier<TableFeatures, TableFeaturesKey> tableFeaturesII = nodeIdent
+ .child(TableFeatures.class, new TableFeaturesKey(tableKey.getId()));
+ List<TableFeatures> tableFeatures = flowCapableNodeConfigured.getTableFeatures();
+ if (tableFeatures != null) {
+ for (TableFeatures tableFeaturesItem : tableFeatures) {
+ // TODO uncomment java.lang.NullPointerException
+ // at
+ // org.opendaylight.openflowjava.protocol.impl.serialization.match.AbstractOxmMatchEntrySerializer.serializeHeader(AbstractOxmMatchEntrySerializer.java:31
+ // allResults.add(JdkFutureAdapters.listenInPoolThread(
+ // tableForwarder.update(tableFeaturesII, null, tableFeaturesItem, nodeIdent)));
+ }
+ }
+ }
+
+ final ListenableFuture<RpcResult<Void>> singleVoidResult = Futures.transform(
+ Futures.allAsList(allResults),
+ ReconcileUtil.<UpdateTableOutput>createRpcResultCondenser("table update"));
+
+ return Futures.transform(singleVoidResult,
+ ReconcileUtil.chainBarrierFlush(PathUtil.digNodePath(nodeIdent), transactionService));
+ }
+
+ private ListenableFuture<RpcResult<Void>> flushAddGroupPortionAndBarrier(
+ final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final ItemSyncBox<Group> groupsPortion) {
+ final List<ListenableFuture<RpcResult<AddGroupOutput>>> allResults = new ArrayList<>();
+ final List<ListenableFuture<RpcResult<UpdateGroupOutput>>> allUpdateResults = new ArrayList<>();
+
+ for (Group group : groupsPortion.getItemsToPush()) {
+ final KeyedInstanceIdentifier<Group, GroupKey> groupIdent = nodeIdent.child(Group.class, group.getKey());
+ allResults.add(JdkFutureAdapters.listenInPoolThread(groupForwarder.add(groupIdent, group, nodeIdent)));
+
+ }
+
+ for (ItemSyncBox.ItemUpdateTuple<Group> groupTuple : groupsPortion.getItemsToUpdate()) {
+ final Group existingGroup = groupTuple.getOriginal();
+ final Group group = groupTuple.getUpdated();
+
+ final KeyedInstanceIdentifier<Group, GroupKey> groupIdent = nodeIdent.child(Group.class, group.getKey());
+ allUpdateResults.add(JdkFutureAdapters.listenInPoolThread(
+ groupForwarder.update(groupIdent, existingGroup, group, nodeIdent)));
+ }
+
+ final ListenableFuture<RpcResult<Void>> singleVoidAddResult = Futures.transform(
+ Futures.allAsList(allResults), ReconcileUtil.<AddGroupOutput>createRpcResultCondenser("group add"));
+
+ final ListenableFuture<RpcResult<Void>> singleVoidUpdateResult = Futures.transform(
+ Futures.allAsList(allUpdateResults),
+ ReconcileUtil.<UpdateGroupOutput>createRpcResultCondenser("group update"));
+
+ final ListenableFuture<RpcResult<Void>> summaryResult = Futures.transform(
+ Futures.allAsList(singleVoidAddResult, singleVoidUpdateResult),
+ ReconcileUtil.<Void>createRpcResultCondenser("group add/update"));
+
+
+ return Futures.transform(summaryResult,
+ ReconcileUtil.chainBarrierFlush(
+ PathUtil.digNodePath(nodeIdent), transactionService));
+ }
+
+ ListenableFuture<RpcResult<Void>> addMissingMeters(final NodeId nodeId,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final ItemSyncBox<Meter> syncBox,
+ final SyncCrudCounters counters) {
+ if (syncBox.isEmpty()) {
+ LOG.trace("no meters configured for node: {} -> SKIPPING", nodeId.getValue());
+ return RpcResultBuilder.<Void>success().buildFuture();
+ }
+
+ final CrudCounts meterCrudCounts = counters.getMeterCrudCounts();
+
+ final List<ListenableFuture<RpcResult<AddMeterOutput>>> allResults = new ArrayList<>();
+ final List<ListenableFuture<RpcResult<UpdateMeterOutput>>> allUpdateResults = new ArrayList<>();
+ for (Meter meter : syncBox.getItemsToPush()) {
+ final KeyedInstanceIdentifier<Meter, MeterKey> meterIdent = nodeIdent.child(Meter.class, meter.getKey());
+ LOG.debug("adding meter {} - absent on device {}",
+ meter.getMeterId(), nodeId);
+ allResults.add(JdkFutureAdapters.listenInPoolThread(
+ meterForwarder.add(meterIdent, meter, nodeIdent)));
+ meterCrudCounts.incAdded();
+ }
+
+ for (ItemSyncBox.ItemUpdateTuple<Meter> meterTuple : syncBox.getItemsToUpdate()) {
+ final Meter existingMeter = meterTuple.getOriginal();
+ final Meter updated = meterTuple.getUpdated();
+ final KeyedInstanceIdentifier<Meter, MeterKey> meterIdent = nodeIdent.child(Meter.class, updated.getKey());
+ LOG.trace("meter {} - needs update on device {}", updated.getMeterId(), nodeId);
+ allUpdateResults.add(JdkFutureAdapters.listenInPoolThread(
+ meterForwarder.update(meterIdent, existingMeter, updated, nodeIdent)));
+ meterCrudCounts.incUpdated();
+ }
+
+ final ListenableFuture<RpcResult<Void>> singleVoidAddResult = Futures.transform(
+ Futures.allAsList(allResults), ReconcileUtil.<AddMeterOutput>createRpcResultCondenser("meter add"));
+
+ final ListenableFuture<RpcResult<Void>> singleVoidUpdateResult = Futures.transform(
+ Futures.allAsList(allUpdateResults),
+ ReconcileUtil.<UpdateMeterOutput>createRpcResultCondenser("meter update"));
+
+ final ListenableFuture<RpcResult<Void>> summaryResults = Futures.transform(
+ Futures.allAsList(singleVoidUpdateResult, singleVoidAddResult),
+ ReconcileUtil.<Void>createRpcResultCondenser("meter add/update"));
+
+ return summaryResults;
+
+ /*
+ return Futures.transform(summaryResults,
+ ReconcileUtil.chainBarrierFlush(PathUtil.digNodePath(nodeIdent), transactionService));
+ */
+ }
+
+ ListenableFuture<RpcResult<Void>> addMissingGroups(final NodeId nodeId,
+ final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final List<ItemSyncBox<Group>> groupsAddPlan,
+ final SyncCrudCounters counters) {
+ if (groupsAddPlan.isEmpty()) {
+ LOG.trace("no groups configured for node: {} -> SKIPPING", nodeId.getValue());
+ return RpcResultBuilder.<Void>success().buildFuture();
+ }
+
+ ListenableFuture<RpcResult<Void>> chainedResult;
+ try {
+ if (!groupsAddPlan.isEmpty()) {
+ final CrudCounts groupCrudCounts = counters.getGroupCrudCounts();
+ groupCrudCounts.setAdded(ReconcileUtil.countTotalPushed(groupsAddPlan));
+ groupCrudCounts.setUpdated(ReconcileUtil.countTotalUpdated(groupsAddPlan));
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("adding groups: planSteps={}, toAddTotal={}, toUpdateTotal={}",
+ groupsAddPlan.size(),
+ groupCrudCounts.getAdded(),
+ groupCrudCounts.getUpdated());
+ }
+
+ chainedResult = flushAddGroupPortionAndBarrier(nodeIdent, groupsAddPlan.get(0));
+ for (final ItemSyncBox<Group> groupsPortion : Iterables.skip(groupsAddPlan, 1)) {
+ chainedResult =
+ Futures.transform(chainedResult, new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input)
+ throws Exception {
+ final ListenableFuture<RpcResult<Void>> result;
+ if (input.isSuccessful()) {
+ result = flushAddGroupPortionAndBarrier(nodeIdent, groupsPortion);
+ } else {
+ // pass through original unsuccessful rpcResult
+ result = Futures.immediateFuture(input);
+ }
+
+ return result;
+ }
+ });
+ }
+ } else {
+ chainedResult = RpcResultBuilder.<Void>success().buildFuture();
+ }
+ } catch (IllegalStateException e) {
+ chainedResult = RpcResultBuilder.<Void>failed()
+ .withError(RpcError.ErrorType.APPLICATION, "failed to add missing groups", e)
+ .buildFuture();
+ }
+
+ return chainedResult;
+ }
+
+
+ public SyncPlanPushStrategyIncrementalImpl setFlowForwarder(final FlowForwarder flowForwarder) {
+ this.flowForwarder = flowForwarder;
+ return this;
+ }
+
+ public SyncPlanPushStrategyIncrementalImpl setTableForwarder(final TableForwarder tableForwarder) {
+ this.tableForwarder = tableForwarder;
+ return this;
+ }
+
+ public SyncPlanPushStrategyIncrementalImpl setMeterForwarder(final MeterForwarder meterForwarder) {
+ this.meterForwarder = meterForwarder;
+ return this;
+ }
+
+ public SyncPlanPushStrategyIncrementalImpl setGroupForwarder(final GroupForwarder groupForwarder) {
+ this.groupForwarder = groupForwarder;
+ return this;
+ }
+
+ public SyncPlanPushStrategyIncrementalImpl setTransactionService(final FlowCapableTransactionService transactionService) {
+ this.transactionService = transactionService;
+ return this;
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl.strategy;
+
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.openflowplugin.applications.frsync.util.ItemSyncBox;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Wraps all the required inputs (diffs) for synchronization strategy execution.
+ */
+public class SynchronizationDiffInput {
+
+ private final InstanceIdentifier<FlowCapableNode> nodeIdent;
+ private final List<ItemSyncBox<Group>> groupsToAddOrUpdate;
+ private final ItemSyncBox<Meter> metersToAddOrUpdate;
+ private final Map<TableKey, ItemSyncBox<Flow>> flowsToAddOrUpdate;
+ private final Map<TableKey, ItemSyncBox<Flow>> flowsToRemove;
+ private final ItemSyncBox<Meter> metersToRemove;
+ private final List<ItemSyncBox<Group>> groupsToRemove;
+
+ public SynchronizationDiffInput(final InstanceIdentifier<FlowCapableNode> nodeIdent,
+ final List<ItemSyncBox<Group>> groupsToAddOrUpdate,
+ final ItemSyncBox<Meter> metersToAddOrUpdate,
+ final Map<TableKey, ItemSyncBox<Flow>> flowsToAddOrUpdate,
+ final Map<TableKey, ItemSyncBox<Flow>> flowsToRemove,
+ final ItemSyncBox<Meter> metersToRemove,
+ final List<ItemSyncBox<Group>> groupsToRemove) {
+ this.nodeIdent = nodeIdent;
+ this.groupsToAddOrUpdate = groupsToAddOrUpdate;
+ this.metersToAddOrUpdate = metersToAddOrUpdate;
+ this.flowsToAddOrUpdate = flowsToAddOrUpdate;
+ this.flowsToRemove = flowsToRemove;
+ this.metersToRemove = metersToRemove;
+ this.groupsToRemove = groupsToRemove;
+ }
+
+ public InstanceIdentifier<FlowCapableNode> getNodeIdent() {
+ return nodeIdent;
+ }
+
+ public List<ItemSyncBox<Group>> getGroupsToAddOrUpdate() {
+ return groupsToAddOrUpdate;
+ }
+
+ public ItemSyncBox<Meter> getMetersToAddOrUpdate() {
+ return metersToAddOrUpdate;
+ }
+
+ public Map<TableKey, ItemSyncBox<Flow>> getFlowsToAddOrUpdate() {
+ return flowsToAddOrUpdate;
+ }
+
+ public Map<TableKey, ItemSyncBox<Flow>> getFlowsToRemove() {
+ return flowsToRemove;
+ }
+
+ public ItemSyncBox<Meter> getMetersToRemove() {
+ return metersToRemove;
+ }
+
+ public List<ItemSyncBox<Group>> getGroupsToRemove() {
+ return groupsToRemove;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.markandsweep;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+
+/**
+ * Identifier of {@link Flow} on device. Switch does not know about flow-id but,
+ * it uses combination of these unique fields: table-id, priority, match.
+ */
+public class SwitchFlowId {
+
+ private final Short tableId;
+
+ private final Integer priority;
+
+ private final Match match;
+
+ public SwitchFlowId(Flow flow) {
+ this.tableId = flow.getTableId();
+ this.priority = flow.getPriority();
+ this.match = flow.getMatch();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((match == null) ? 0 : match.hashCode());
+ result = prime * result + ((priority == null) ? 0 : priority.hashCode());
+ result = prime * result + ((tableId == null) ? 0 : tableId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ SwitchFlowId other = (SwitchFlowId) obj;
+ if (match == null) {
+ if (other.match != null)
+ return false;
+ } else if (!match.equals(other.match))
+ return false;
+ if (priority == null) {
+ if (other.priority != null)
+ return false;
+ } else if (!priority.equals(other.priority))
+ return false;
+ if (tableId == null) {
+ if (other.tableId != null)
+ return false;
+ } else if (!tableId.equals(other.tableId))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+/**
+ * General placeholder for add/update/remove counts.
+ */
+public class CrudCounts {
+ private int added;
+ private int updated;
+ private int removed;
+
+ public int getAdded() {
+ return added;
+ }
+
+ public void setAdded(final int added) {
+ this.added = added;
+ }
+
+ public int getUpdated() {
+ return updated;
+ }
+
+ public void setUpdated(final int updated) {
+ this.updated = updated;
+ }
+
+ public int getRemoved() {
+ return removed;
+ }
+
+ public void setRemoved(final int removed) {
+ this.removed = removed;
+ }
+
+ public void incAdded() {
+ added++;
+ }
+
+ public void incUpdated() {
+ updated++;
+ }
+
+ public void incRemoved() {
+ removed++;
+ }
+
+ public void decAdded() {
+ added--;
+ }
+
+ public void decUpdated() {
+ updated--;
+ }
+
+ public void decRemoved() {
+ removed--;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.openflowplugin.applications.frsync.markandsweep.SwitchFlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helpers for flow lookups in {@link FlowCapableNode}.
+ */
+public final class FlowCapableNodeLookups {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FlowCapableNodeLookups.class);
+
+ private FlowCapableNodeLookups() {
+ throw new IllegalAccessError("non instantiable util class");
+ }
+
+ @Nonnull
+ public static Map<Short, Table> wrapTablesToMap(@Nullable final List<Table> tables) {
+ final Map<Short, Table> tableMap;
+
+ if (tables == null) {
+ tableMap = Collections.emptyMap();
+ } else {
+ LOG.trace("tables found: {}", tables.size());
+ tableMap = new HashMap<>();
+ for (Table table : tables) {
+ tableMap.put(table.getId(), table);
+ }
+ }
+
+ return tableMap;
+ }
+
+ @Nonnull
+ public static Map<SwitchFlowId, Flow> wrapFlowsToMap(@Nullable final List<Flow> flows) {
+ final Map<SwitchFlowId, Flow> flowMap;
+
+ if (flows == null) {
+ flowMap = Collections.emptyMap();
+ } else {
+ LOG.trace("flows found: {}", flows.size());
+ flowMap = new HashMap<>();
+ for (Flow flow : flows) {
+ flowMap.put(new SwitchFlowId(flow), flow);
+ }
+ }
+
+ return flowMap;
+ }
+
+ public static Flow flowMapLookupExisting(Flow flow, Map<SwitchFlowId, Flow> flowConfigMap) {
+ return flowConfigMap.get(new SwitchFlowId(flow));
+ }
+
+ @Nonnull
+ public static Map<MeterId, Meter> wrapMetersToMap(@Nullable final List<Meter> meters) {
+ final Map<MeterId, Meter> meterMap;
+
+ if (meters == null) {
+ meterMap = Collections.emptyMap();
+ } else {
+ LOG.trace("meters found: {}", meters.size());
+ meterMap = new HashMap<>();
+ for (Meter meter : meters) {
+ meterMap.put(meter.getMeterId(), meter);
+ }
+ }
+
+ return meterMap;
+ }
+
+ @Nonnull
+ public static Map<Long, Group> wrapGroupsToMap(@Nullable final List<Group> groups) {
+ final Map<Long, Group> groupMap;
+
+ if (groups == null) {
+ groupMap = Collections.emptyMap();
+ } else {
+ LOG.trace("groups found: {}", groups.size());
+ groupMap = new HashMap<>();
+ for (Group group : groups) {
+ groupMap.put(group.getGroupId().getValue(), group);
+ }
+ }
+
+ return groupMap;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.FutureCallback;
+import java.util.Arrays;
+import java.util.Collection;
+import javax.annotation.Nullable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Util methods for {@link com.google.common.util.concurrent.ListenableFuture} chaining.
+ */
+public class FxChainUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FxChainUtil.class);
+
+
+ public static FutureCallback<RpcResult<Void>> logResultCallback(final NodeId nodeId, final String prefix) {
+ return new FutureCallback<RpcResult<Void>>() {
+ @Override
+ public void onSuccess(@Nullable final RpcResult<Void> result) {
+ if (result != null) {
+ if (result.isSuccessful()) {
+ LOG.debug(prefix + " finished successfully: {}", nodeId.getValue());
+ } else {
+ final Collection<RpcError> errors = MoreObjects.firstNonNull(result.getErrors(), ImmutableList.<RpcError>of());
+ LOG.debug(prefix + " failed: {} -> {}", nodeId.getValue(), Arrays.toString(errors.toArray()));
+ }
+ } else {
+ LOG.debug(prefix + "reconciliation failed: {} -> null result", nodeId.getValue());
+ }
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ LOG.debug(prefix + "reconciliation failed seriously: {}", nodeId.getValue(), t);
+ }
+ };
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Holder for items to be pushed to device.
+ * Contains two sets of groups -set of items to be pushed and set of tuples for update.
+ */
+public class ItemSyncBox<I> {
+
+ private Set<I> itemsToPush = new LinkedHashSet<>();
+ private Set<ItemUpdateTuple<I>> itemsToUpdate = new LinkedHashSet<>();
+
+ public Set<I> getItemsToPush() {
+ return itemsToPush;
+ }
+
+ public Set<ItemUpdateTuple<I>> getItemsToUpdate() {
+ return itemsToUpdate;
+ }
+
+ public boolean isEmpty() {
+ return itemsToPush.isEmpty() && itemsToUpdate.isEmpty();
+ }
+
+ /**
+ * Tuple holder for original and updated item.
+ * @param <I> basic type
+ */
+ public static final class ItemUpdateTuple<I> {
+ private final I original;
+ private final I updated;
+
+ public ItemUpdateTuple(I original, I updated) {
+ this.original = original;
+ this.updated = updated;
+ }
+
+ public I getOriginal() {
+ return original;
+ }
+
+ public I getUpdated() {
+ return updated;
+ }
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Basic {@link InstanceIdentifier} related tools.
+ */
+public class PathUtil {
+ public static NodeId digNodeId(final InstanceIdentifier<?> nodeIdent) {
+ return nodeIdent.firstKeyOf(Node.class, NodeKey.class).getId();
+ }
+
+ public static InstanceIdentifier<Node> digNodePath(final InstanceIdentifier<FlowCapableNode> nodeIdent) {
+ return nodeIdent.firstIdentifierOf(Node.class);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import javax.annotation.Nullable;
+import org.opendaylight.openflowplugin.applications.frsync.markandsweep.SwitchFlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+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.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Util methods for group reconcil task (future chaining, transforms).
+ */
+public class ReconcileUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ReconcileUtil.class);
+
+ /**
+ * @param previousItemAction description for case when the triggering future contains failure
+ * @param <D> type of rpc output (gathered in list)
+ * @return single rpc result of type Void honoring all partial rpc results
+ */
+ public static <D> Function<List<RpcResult<D>>, RpcResult<Void>> createRpcResultCondenser(final String previousItemAction) {
+ return new Function<List<RpcResult<D>>, RpcResult<Void>>() {
+ @Nullable
+ @Override
+ public RpcResult<Void> apply(@Nullable final List<RpcResult<D>> input) {
+ final RpcResultBuilder<Void> resultSink;
+ if (input != null) {
+ List<RpcError> errors = new ArrayList<>();
+ for (RpcResult<D> rpcResult : input) {
+ if (!rpcResult.isSuccessful()) {
+ errors.addAll(rpcResult.getErrors());
+ }
+ }
+ if (errors.isEmpty()) {
+ resultSink = RpcResultBuilder.success();
+ } else {
+ resultSink = RpcResultBuilder.<Void>failed().withRpcErrors(errors);
+ }
+ } else {
+ resultSink = RpcResultBuilder.<Void>failed()
+ .withError(RpcError.ErrorType.APPLICATION, "previous " + previousItemAction + " failed");
+
+ }
+
+ return resultSink.build();
+ }
+ };
+ }
+
+ /**
+ * @param actionDescription description for case when the triggering future contains failure
+ * @param <D> type of rpc output (gathered in list)
+ * @return single rpc result of type Void honoring all partial rpc results
+ */
+ public static <D> Function<RpcResult<D>, RpcResult<Void>> createRpcResultToVoidFunction(final String actionDescription) {
+ return new Function<RpcResult<D>, RpcResult<Void>>() {
+ @Nullable
+ @Override
+ public RpcResult<Void> apply(@Nullable final RpcResult<D> input) {
+ final RpcResultBuilder<Void> resultSink;
+ if (input != null) {
+ List<RpcError> errors = new ArrayList<>();
+ if (!input.isSuccessful()) {
+ errors.addAll(input.getErrors());
+ resultSink = RpcResultBuilder.<Void>failed().withRpcErrors(errors);
+ } else {
+ resultSink = RpcResultBuilder.success();
+ }
+ } else {
+ resultSink = RpcResultBuilder.<Void>failed()
+ .withError(RpcError.ErrorType.APPLICATION, "action of " + actionDescription + " failed");
+
+ }
+
+ return resultSink.build();
+ }
+ };
+ }
+
+ /**
+ * @param nodeIdent flow capable node path - target device for routed rpc
+ * @param flowCapableTransactionService barrier rpc service
+ * @return async barrier result
+ */
+ public static AsyncFunction<RpcResult<Void>, RpcResult<Void>> chainBarrierFlush(
+ final InstanceIdentifier<Node> nodeIdent,
+ final FlowCapableTransactionService flowCapableTransactionService) {
+ return new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final RpcResult<Void> input) throws Exception {
+ final SendBarrierInput barrierInput = new SendBarrierInputBuilder()
+ .setNode(new NodeRef(nodeIdent))
+ .build();
+ return JdkFutureAdapters.listenInPoolThread(flowCapableTransactionService.sendBarrier(barrierInput));
+ }
+ };
+ }
+
+ /**
+ * @param nodeId target node
+ * @param installedGroupsArg groups resent on device
+ * @param pendingGroups groups configured for device
+ * @return list of safe synchronization steps with updates
+ */
+ public static List<ItemSyncBox<Group>> resolveAndDivideGroupDiffs(final NodeId nodeId,
+ final Map<Long, Group> installedGroupsArg,
+ final Collection<Group> pendingGroups) {
+ return resolveAndDivideGroupDiffs(nodeId, installedGroupsArg, pendingGroups, true);
+ }
+
+ /**
+ * @param nodeId target node
+ * @param installedGroupsArg groups resent on device
+ * @param pendingGroups groups configured for device
+ * @param gatherUpdates check content of pending item if present on device (and create update task eventually)
+ * @return list of safe synchronization steps
+ */
+ public static List<ItemSyncBox<Group>> resolveAndDivideGroupDiffs(final NodeId nodeId,
+ final Map<Long, Group> installedGroupsArg,
+ final Collection<Group> pendingGroups,
+ final boolean gatherUpdates) {
+
+ final Map<Long, Group> installedGroups = new HashMap<>(installedGroupsArg);
+ final List<ItemSyncBox<Group>> plan = new ArrayList<>();
+
+ while (!Iterables.isEmpty(pendingGroups)) {
+ final ItemSyncBox<Group> stepPlan = new ItemSyncBox<>();
+ final Iterator<Group> iterator = pendingGroups.iterator();
+ final Map<Long, Group> installIncrement = new HashMap<>();
+
+ while (iterator.hasNext()) {
+ final Group group = iterator.next();
+
+ final Group existingGroup = installedGroups.get(group.getGroupId().getValue());
+ if (existingGroup != null) {
+ if (!gatherUpdates) {
+ iterator.remove();
+ } else {
+ // check buckets and eventually update
+ if (group.equals(existingGroup)) {
+ iterator.remove();
+ } else {
+ if (checkGroupPrecondition(installedGroups.keySet(), group)) {
+ iterator.remove();
+ LOG.trace("Group {} on device {} differs - planned for update", group.getGroupId(), nodeId);
+ stepPlan.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(existingGroup, group));
+ }
+ }
+ }
+ } else if (checkGroupPrecondition(installedGroups.keySet(), group)) {
+ iterator.remove();
+ installIncrement.put(group.getGroupId().getValue(), group);
+ stepPlan.getItemsToPush().add(group);
+ }
+ }
+
+ if (!stepPlan.isEmpty()) {
+ // atomic update of installed flows in order to keep plan portions clean of local group dependencies
+ installedGroups.putAll(installIncrement);
+ plan.add(stepPlan);
+ } else if (!pendingGroups.isEmpty()) {
+ LOG.warn("Failed to resolve and divide groups into preconditions-match based ordered plan: {}, " +
+ "resolving stuck at level {}", nodeId.getValue(), plan.size());
+ throw new IllegalStateException("Failed to resolve and divide groups when matching preconditions");
+ }
+ }
+
+ return plan;
+ }
+
+ public static boolean checkGroupPrecondition(final Set<Long> installedGroupIds, final Group pendingGroup) {
+ boolean okToInstall = true;
+ // check each bucket in the pending group
+ for (Bucket bucket : pendingGroup.getBuckets().getBucket()) {
+ for (Action action : bucket.getAction()) {
+ // if the output action is a group
+ if (GroupActionCase.class.equals(action.getAction().getImplementedInterface())) {
+ Long groupId = ((GroupActionCase) (action.getAction())).getGroupAction().getGroupId();
+ // see if that output group is installed
+ if (!installedGroupIds.contains(groupId)) {
+ // if not installed, we have missing dependencies and cannot install this pending group
+ okToInstall = false;
+ break;
+ }
+ }
+ }
+ if (!okToInstall) {
+ break;
+ }
+ }
+ return okToInstall;
+ }
+
+ public static <E> int countTotalPushed(final Iterable<ItemSyncBox<E>> groupsAddPlan) {
+ int count = 0;
+ for (ItemSyncBox<E> groupItemSyncBox : groupsAddPlan) {
+ count += groupItemSyncBox.getItemsToPush().size();
+ }
+ return count;
+ }
+
+ public static <E> int countTotalUpdated(final Iterable<ItemSyncBox<E>> groupsAddPlan) {
+ int count = 0;
+ for (ItemSyncBox<E> groupItemSyncBox : groupsAddPlan) {
+ count += groupItemSyncBox.getItemsToUpdate().size();
+ }
+ return count;
+ }
+
+ /**
+ * @param nodeId target node
+ * @param meterOperationalMap meters present on device
+ * @param metersConfigured meters configured for device
+ * @param gatherUpdates check content of pending item if present on device (and create update task eventually)
+ * @return synchronization box
+ */
+ public static ItemSyncBox<Meter> resolveMeterDiffs(final NodeId nodeId,
+ final Map<MeterId, Meter> meterOperationalMap,
+ final List<Meter> metersConfigured,
+ final boolean gatherUpdates) {
+ LOG.trace("resolving meters for {}", nodeId);
+ final ItemSyncBox<Meter> syncBox = new ItemSyncBox<>();
+ for (Meter meter : metersConfigured) {
+ final Meter existingMeter = meterOperationalMap.get(meter.getMeterId());
+ if (existingMeter == null) {
+ syncBox.getItemsToPush().add(meter);
+ } else {
+ // compare content and eventually update
+ if (gatherUpdates && !meter.equals(existingMeter)) {
+ syncBox.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(existingMeter, meter));
+ }
+ }
+ }
+ return syncBox;
+ }
+
+ /**
+ * @param flowsConfigured flows resent on device
+ * @param flowOperationalMap flows configured for device
+ * @param gatherUpdates check content of pending item if present on device (and create update task eventually)
+ * @return list of safe synchronization steps
+ */
+ @VisibleForTesting
+ static ItemSyncBox<Flow> resolveFlowDiffsInTable(final List<Flow> flowsConfigured,
+ final Map<SwitchFlowId, Flow> flowOperationalMap,
+ final boolean gatherUpdates) {
+ final ItemSyncBox<Flow> flowsSyncBox = new ItemSyncBox<>();
+ // loop configured flows and check if already present on device
+ for (final Flow flow : flowsConfigured) {
+ final Flow existingFlow = FlowCapableNodeLookups.flowMapLookupExisting(flow, flowOperationalMap);
+
+ if (existingFlow == null) {
+ flowsSyncBox.getItemsToPush().add(flow);
+ } else {
+ // check instructions and eventually update
+ if (gatherUpdates && !Objects.equals(flow.getInstructions(), existingFlow.getInstructions())) {
+ flowsSyncBox.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(existingFlow, flow));
+ }
+ }
+ }
+ return flowsSyncBox;
+ }
+
+ /**
+ * @param nodeId target node
+ * @param tableOperationalMap flow-tables resent on device
+ * @param tablesConfigured flow-tables configured for device
+ * @param gatherUpdates check content of pending item if present on device (and create update task eventually)
+ * @return map : key={@link TableKey}, value={@link ItemSyncBox} of safe synchronization steps
+ */
+ public static Map<TableKey, ItemSyncBox<Flow>> resolveFlowDiffsInAllTables(final NodeId nodeId,
+ final Map<Short, Table> tableOperationalMap,
+ final List<Table> tablesConfigured,
+ final boolean gatherUpdates) {
+ LOG.trace("resolving flows in tables for {}", nodeId);
+ final Map<TableKey, ItemSyncBox<Flow>> tableFlowSyncBoxes = new HashMap<>();
+ for (final Table tableConfigured : tablesConfigured) {
+ final List<Flow> flowsConfigured = tableConfigured.getFlow();
+ if (flowsConfigured == null || flowsConfigured.isEmpty()) {
+ continue;
+ }
+
+ // lookup table (on device)
+ final Table tableOperational = tableOperationalMap.get(tableConfigured.getId());
+ // wrap existing (on device) flows in current table into map
+ final Map<SwitchFlowId, Flow> flowOperationalMap = FlowCapableNodeLookups.wrapFlowsToMap(
+ tableOperational != null
+ ? tableOperational.getFlow()
+ : null);
+
+
+ final ItemSyncBox<Flow> flowsSyncBox = resolveFlowDiffsInTable(
+ flowsConfigured, flowOperationalMap, gatherUpdates);
+ if (!flowsSyncBox.isEmpty()) {
+ tableFlowSyncBoxes.put(tableConfigured.getKey(), flowsSyncBox);
+ }
+ }
+ return tableFlowSyncBoxes;
+ }
+
+ public static List<Group> safeGroups(FlowCapableNode node) {
+ if (node == null) {
+ return Collections.emptyList();
+ }
+
+ return MoreObjects.firstNonNull(node.getGroup(), ImmutableList.<Group>of());
+ }
+
+ public static List<Table> safeTables(FlowCapableNode node) {
+ if (node == null) {
+ return Collections.emptyList();
+ }
+
+ return MoreObjects.firstNonNull(node.getTable(), ImmutableList.<Table>of());
+ }
+
+ public static List<Meter> safeMeters(FlowCapableNode node) {
+ if (node == null) {
+ return Collections.emptyList();
+ }
+
+ return MoreObjects.firstNonNull(node.getMeter(), ImmutableList.<Meter>of());
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Holder of registration request for fresh operational.
+ */
+public class RetryRegistry {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RetryRegistry.class);
+ private final Map<NodeId, Date> registration = new ConcurrentHashMap<>();
+ public static final String DATE_AND_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
+
+ public Date register(NodeId nodeId) {
+ Date timestamp = new Date();
+ registration.put(nodeId, timestamp);
+ if (timestamp != null) {
+ LOG.debug("Registered for next consistent operational: {}", nodeId.getValue());
+ }
+ return timestamp;
+ }
+
+ public Date unregisterIfRegistered(NodeId nodeId) {
+ Date timestamp = registration.remove(nodeId);
+ if (timestamp != null) {
+ LOG.debug("Unregistered for next consistent operational: {}", nodeId.getValue());
+ }
+ return timestamp;
+ }
+
+ public boolean isRegistered(NodeId nodeId) {
+ return registration.get(nodeId) != null;
+ }
+
+ public Date getRegistration(NodeId nodeId) {
+ return registration.get(nodeId);
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import java.util.concurrent.Semaphore;
+import javax.annotation.Nonnull;
+import org.opendaylight.openflowplugin.applications.frsync.SemaphoreKeeper;
+
+/**
+ * Key-based semaphore provider.
+ */
+public class SemaphoreKeeperGuavaImpl<K> implements SemaphoreKeeper<K> {
+
+ private LoadingCache<K, Semaphore> semaphoreCache;
+
+ public SemaphoreKeeperGuavaImpl(final int permits, final boolean fair) {
+ semaphoreCache = CacheBuilder.newBuilder()
+ .concurrencyLevel(1)
+ .weakValues()
+ .build(new CacheLoader<K, Semaphore>() {
+ @Override
+ public Semaphore load(final K key) throws Exception {
+ return new Semaphore(permits, fair) {
+ private static final long serialVersionUID = 1L;
+ };
+ }
+ });
+ }
+
+ @Override
+ public Semaphore summonGuard(final @Nonnull K key) {
+ return semaphoreCache.getUnchecked(key);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " size:" + (semaphoreCache == null ? null : semaphoreCache.size()) + " " + semaphoreCache;
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+/**
+ * One-shot (per sync) placeholder for counts of added/updated/removed flows/groups/meters.
+ */
+public class SyncCrudCounters {
+
+ private final CrudCounts flowCrudCounts;
+ private final CrudCounts groupCrudCounts;
+ private final CrudCounts meterCrudCounts;
+ private long startNano;
+
+ public SyncCrudCounters() {
+ flowCrudCounts = new CrudCounts();
+ groupCrudCounts = new CrudCounts();
+ meterCrudCounts = new CrudCounts();
+ }
+
+ public CrudCounts getFlowCrudCounts() {
+ return flowCrudCounts;
+ }
+
+ public CrudCounts getGroupCrudCounts() {
+ return groupCrudCounts;
+ }
+
+ public CrudCounts getMeterCrudCounts() {
+ return meterCrudCounts;
+ }
+
+
+ public long getStartNano() {
+ return startNano;
+ }
+
+ public void setStartNano(final long startNano) {
+ this.startNano = startNano;
+ }
+
+ public void resetAll() {
+ getGroupCrudCounts().setUpdated(0);
+ getGroupCrudCounts().setAdded(0);
+ getGroupCrudCounts().setRemoved(0);
+
+ getFlowCrudCounts().setUpdated(0);
+ getFlowCrudCounts().setAdded(0);
+ getFlowCrudCounts().setRemoved(0);
+
+ getMeterCrudCounts().setUpdated(0);
+ getMeterCrudCounts().setAdded(0);
+ getMeterCrudCounts().setRemoved(0);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.impl.SyncReactorFutureZipDecorator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+
+/**
+ * Simple compression queue entry for {@link SyncReactorFutureZipDecorator}.
+ */
+public class ZipQueueEntry {
+ private final FlowCapableNode after;
+ private final FlowCapableNode before;
+ private final LogicalDatastoreType dsTypeBefore;
+
+ public ZipQueueEntry(final FlowCapableNode after, final FlowCapableNode before,
+ final LogicalDatastoreType dsTypeBefore) {
+ this.after = after;
+ this.before = before;
+ this.dsTypeBefore = dsTypeBefore;
+ }
+
+ public FlowCapableNode getLeft() {
+ return after;
+ }
+
+ public FlowCapableNode getRight() {
+ return before;
+ }
+
+ public LogicalDatastoreType getDsType() {
+ return dsTypeBefore;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<features name="openflowplugin-applications-frs-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+ <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.netconf/features-netconf-connector/${netconf.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+
+ <!-- DEV COMMAND SUPPORT -->
+ <feature name='odl-openflowplugin-application-frsync' description="OpenDaylight :: Openflow Plugin :: FR-Synchronization" version='${project.version}'>
+ <feature version='${netconf.version}'>odl-netconf-connector-all</feature>
+ <feature version='${mdsal.version}'>odl-netconf-mdsal</feature>
+ <bundle>mvn:org.opendaylight.openflowplugin.applications/forwardingrules-sync/${project.version}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/69-forwardingrules-sync.xml">mvn:org.opendaylight.openflowplugin.applications/forwardingrules-sync/${project.version}/xml/config</configfile>
+ </feature>
+
+</features>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2016 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
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="broker" interface="org.opendaylight.controller.sal.binding.api.BindingAwareBroker"/>
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
+ <reference id="rpcRegistry" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"/>
+
+ <bean id="frSync" class="org.opendaylight.openflowplugin.applications.frsync.impl.ForwardingRulesSyncProvider"
+ destroy-method="close">
+ <argument ref="broker"/>
+ <argument ref="dataBroker"/>
+ <argument ref="rpcRegistry"/>
+ </bean>
+
+</blueprint>
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.BandId;
+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.band.type.DropBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.MeterBandHeadersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeaderBuilder;
+
+/**
+ * Provides create methods for dataObjects involved in
+ * {@link org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener} by inventory.
+ */
+public class DSInputFactory {
+ public static Group createGroup(final long groupIdValue) {
+ final Buckets buckets = new BucketsBuilder()
+ .setBucket(Collections.<Bucket>emptyList())
+ .build();
+ return new GroupBuilder()
+ .setGroupId(new GroupId(groupIdValue))
+ .setBuckets(buckets)
+ .build();
+ }
+
+ public static Group createGroupWithAction(final long groupIdValue) {
+ final Buckets buckets = new BucketsBuilder()
+ .setBucket(Collections.singletonList(new BucketBuilder()
+ .setAction(Collections.singletonList(new ActionBuilder()
+ .setAction(new OutputActionCaseBuilder()
+ .setOutputAction(new OutputActionBuilder()
+ .setOutputNodeConnector(new Uri("ut-port-1"))
+ .build())
+ .build())
+ .build()))
+ .build()))
+ .build();
+ return new GroupBuilder()
+ .setGroupId(new GroupId(groupIdValue))
+ .setBuckets(buckets)
+ .build();
+ }
+
+ public static Flow createFlow(final String flowIdValue, final int priority) {
+ return new FlowBuilder()
+ .setId(new FlowId(flowIdValue))
+ .setPriority(priority)
+ .setTableId((short) 42)
+ .setMatch(new MatchBuilder().build())
+ .build();
+ }
+
+ public static Flow createFlowWithInstruction(final String flowIdValue, final int priority) {
+ return new FlowBuilder()
+ .setId(new FlowId(flowIdValue))
+ .setPriority(priority)
+ .setTableId((short) 42)
+ .setMatch(new MatchBuilder().build())
+ .setInstructions(new InstructionsBuilder()
+ .setInstruction(Collections.singletonList(new InstructionBuilder()
+ .setInstruction(new ApplyActionsCaseBuilder()
+ .setApplyActions(new ApplyActionsBuilder()
+ .setAction(Collections.singletonList(new ActionBuilder()
+ .setAction(new OutputActionCaseBuilder()
+ .setOutputAction(new OutputActionBuilder()
+ .setOutputNodeConnector(new Uri("ut-port-1"))
+ .build())
+ .build())
+ .build()))
+ .build())
+ .build())
+ .build()))
+ .build())
+ .build();
+ }
+
+ public static Meter createMeter(final Long meterIdValue) {
+ return new MeterBuilder()
+ .setMeterId(new MeterId(meterIdValue))
+ .build();
+ }
+
+ public static Meter createMeterWithBody(final Long meterIdValue) {
+ return new MeterBuilder()
+ .setMeterId(new MeterId(meterIdValue))
+ .setMeterBandHeaders(new MeterBandHeadersBuilder()
+ .setMeterBandHeader(Collections.singletonList(new MeterBandHeaderBuilder()
+ .setBandId(new BandId(42L))
+ .setBandType(new DropBuilder()
+ .setDropRate(43L)
+ .build())
+ .build()))
+ .build())
+ .build();
+ }
+
+ public static Group createGroupWithPreconditions(final long groupIdValue, final long... requiredId) {
+ final List<Action> actionBag = new ArrayList<>();
+ for (long groupIdPrecondition : requiredId) {
+ final GroupAction groupAction = new GroupActionBuilder()
+ .setGroupId(groupIdPrecondition)
+ .build();
+ final GroupActionCase groupActionCase = new GroupActionCaseBuilder()
+ .setGroupAction(groupAction)
+ .build();
+ final Action action = new ActionBuilder()
+ .setAction(groupActionCase)
+ .build();
+ actionBag.add(action);
+ }
+
+ final Bucket bucket = new BucketBuilder()
+ .setAction(actionBag)
+ .build();
+ final Buckets buckets = new BucketsBuilder()
+ .setBucket(Collections.singletonList(bucket))
+ .build();
+
+ return new GroupBuilder()
+ .setGroupId(new GroupId(groupIdValue))
+ .setBuckets(buckets)
+ .build();
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link FlowForwarder}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class FlowForwarderTest {
+ private final NodeKey s1Key = new NodeKey(new NodeId("S1"));
+ private final TableKey tableKey = new TableKey((short) 2);
+ private final FlowId flowId = new FlowId("test_Flow");
+ private final FlowKey flowKey = new FlowKey(flowId);
+ private final Match emptyMatch = new MatchBuilder().build();
+ private final Flow flow = new FlowBuilder()
+ .setId(flowId)
+ .setTableId((short) 2)
+ .setMatch(emptyMatch)
+ .build();
+
+ private final KeyedInstanceIdentifier<Node, NodeKey> nodePath = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, s1Key);
+ private final InstanceIdentifier<FlowCapableNode> flowCapableNodePath = nodePath
+ .augmentation(FlowCapableNode.class);
+ private final InstanceIdentifier<Table> tableII = flowCapableNodePath.child(Table.class, tableKey);
+ private final InstanceIdentifier<Flow> flowPath = tableII.child(Flow.class, flowKey);
+
+ private FlowForwarder flowForwarder;
+
+ @Mock
+ private SalFlowService salFlowService;
+ @Captor
+ private ArgumentCaptor<AddFlowInput> addFlowInputCpt;
+ @Captor
+ private ArgumentCaptor<UpdateFlowInput> updateFlowInputCpt;
+ @Captor
+ private ArgumentCaptor<RemoveFlowInput> removeFlowInputCpt;
+
+
+ @Before
+ public void setUp() throws Exception {
+ flowForwarder = new FlowForwarder(salFlowService);
+ }
+
+ @Test
+ public void addTest() throws Exception {
+ Mockito.when(salFlowService.addFlow(addFlowInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(
+ new AddFlowOutputBuilder()
+ .setTransactionId(new TransactionId(BigInteger.ONE))
+ .build()).buildFuture());
+
+ final Future<RpcResult<AddFlowOutput>> addResult = flowForwarder.add(flowPath, flow, flowCapableNodePath);
+
+ Mockito.verify(salFlowService).addFlow(Matchers.<AddFlowInput>any());
+ final AddFlowInput flowInput = addFlowInputCpt.getValue();
+ Assert.assertEquals(2, flowInput.getTableId().shortValue());
+ Assert.assertEquals(emptyMatch, flowInput.getMatch());
+ Assert.assertEquals(null, flowInput.getInstructions());
+ Assert.assertEquals(nodePath, flowInput.getNode().getValue());
+ Assert.assertEquals(flowPath, flowInput.getFlowRef().getValue());
+ Assert.assertEquals(null, flowInput.isStrict());
+
+
+ final RpcResult<AddFlowOutput> addFlowOutputRpcResult = addResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(addFlowOutputRpcResult.isSuccessful());
+ final AddFlowOutput resultValue = addFlowOutputRpcResult.getResult();
+ Assert.assertEquals(1, resultValue.getTransactionId().getValue().intValue());
+ }
+
+ @Test
+ public void updateTest() throws Exception {
+ Mockito.when(salFlowService.updateFlow(updateFlowInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(
+ new UpdateFlowOutputBuilder()
+ .setTransactionId(new TransactionId(BigInteger.ONE))
+ .build()).buildFuture());
+
+ final Instructions originalInstructions = new InstructionsBuilder()
+ .setInstruction(Collections.singletonList(new InstructionBuilder()
+ .setInstruction(new ApplyActionsCaseBuilder()
+ .setApplyActions(new ApplyActionsBuilder()
+ .setAction(Collections.singletonList(new ActionBuilder()
+ .setAction(new DropActionCaseBuilder()
+ .build())
+ .build())
+ ).build()
+ ).build())
+ .build())
+ ).build();
+
+ final Flow flowUpdated = new FlowBuilder(flow)
+ .setInstructions(originalInstructions)
+ .setMatch(new MatchBuilder().build())
+ .build();
+
+ final Future<RpcResult<UpdateFlowOutput>> updateResult = flowForwarder.update(flowPath, flow, flowUpdated, flowCapableNodePath);
+
+ Mockito.verify(salFlowService).updateFlow(Matchers.<UpdateFlowInput>any());
+ final UpdateFlowInput updateFlowInput = updateFlowInputCpt.getValue();
+ final OriginalFlow flowOrigInput = updateFlowInput.getOriginalFlow();
+ final UpdatedFlow flowInput = updateFlowInput.getUpdatedFlow();
+
+ Assert.assertEquals(nodePath, updateFlowInput.getNode().getValue());
+ Assert.assertEquals(flowPath, updateFlowInput.getFlowRef().getValue());
+
+ Assert.assertEquals(2, flowInput.getTableId().shortValue());
+ Assert.assertEquals(emptyMatch, flowInput.getMatch());
+ Assert.assertEquals(originalInstructions, flowInput.getInstructions());
+ Assert.assertEquals(true, flowInput.isStrict());
+
+ Assert.assertEquals(2, flowOrigInput.getTableId().shortValue());
+ Assert.assertEquals(emptyMatch, flowOrigInput.getMatch());
+ Assert.assertEquals(null, flowOrigInput.getInstructions());
+ Assert.assertEquals(true, flowOrigInput.isStrict());
+
+
+ final RpcResult<UpdateFlowOutput> updateFlowOutputRpcResult = updateResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(updateFlowOutputRpcResult.isSuccessful());
+ final UpdateFlowOutput resultValue = updateFlowOutputRpcResult.getResult();
+ Assert.assertEquals(1, resultValue.getTransactionId().getValue().intValue());
+ }
+
+ @Test
+ public void removeTest() throws Exception {
+ Mockito.when(salFlowService.removeFlow(removeFlowInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(
+ new RemoveFlowOutputBuilder()
+ .setTransactionId(new TransactionId(BigInteger.ONE))
+ .build()).buildFuture());
+
+ final Flow removeFlow = new FlowBuilder(flow).build();
+ final Future<RpcResult<RemoveFlowOutput>> removeResult = flowForwarder.remove(flowPath, removeFlow, flowCapableNodePath);
+
+ Mockito.verify(salFlowService).removeFlow(Matchers.<RemoveFlowInput>any());
+ final RemoveFlowInput flowInput = removeFlowInputCpt.getValue();
+ Assert.assertEquals(2, flowInput.getTableId().shortValue());
+ Assert.assertEquals(emptyMatch, flowInput.getMatch());
+ Assert.assertEquals(null, flowInput.getInstructions());
+ Assert.assertEquals(true, flowInput.isStrict());
+
+
+ final RpcResult<RemoveFlowOutput> removeFlowOutputRpcResult = removeResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(removeFlowOutputRpcResult.isSuccessful());
+ final RemoveFlowOutput resultValue = removeFlowOutputRpcResult.getResult();
+ Assert.assertEquals(1, resultValue.getTransactionId().getValue().intValue());
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+/**
+ * Test for {@link ForwardingRulesSyncProvider}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ForwardingRulesSyncProviderTest {
+
+ private ForwardingRulesSyncProvider provider;
+ @Mock
+ private DataBroker dataBroker;
+ @Mock
+ private RpcConsumerRegistry rpcRegistry;
+ @Mock
+ private BindingAwareBroker broker;
+ @Mock
+ private BindingAwareBroker.ProviderContext providerContext;
+
+ @Before
+ public void setUp() throws Exception {
+ Mockito.when(rpcRegistry.getRpcService(Matchers.<Class<? extends RpcService>>any()))
+ .thenAnswer(new Answer<RpcService>() {
+ @Override
+ public RpcService answer(final InvocationOnMock invocation) throws Throwable {
+ Class<? extends RpcService> serviceType = (Class<? extends RpcService>) invocation.getArguments()[0];
+ return Mockito.mock(serviceType);
+ }
+ });
+
+ provider = new ForwardingRulesSyncProvider(broker, dataBroker, rpcRegistry);
+ Mockito.verify(rpcRegistry).getRpcService(SalTableService.class);
+ Mockito.verify(rpcRegistry).getRpcService(SalFlatBatchService.class);
+ Mockito.verify(broker).registerProvider(provider);
+ }
+
+ @Test
+ public void testOnSessionInitiated() throws Exception {
+ provider.onSessionInitiated(providerContext);
+
+ Mockito.verify(dataBroker, Mockito.times(2)).registerDataTreeChangeListener(
+ Matchers.<DataTreeIdentifier<FlowCapableNode>>any(),
+ Matchers.<DataTreeChangeListener<FlowCapableNode>>any());
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import java.math.BigInteger;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link GroupForwarder}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class GroupForwarderTest {
+
+ private final NodeKey s1Key = new NodeKey(new NodeId("S1"));
+ private final GroupId groupId = new GroupId(42L);
+ private final GroupKey groupKey = new GroupKey(groupId);
+ private final Group group = new GroupBuilder()
+ .setGroupId(groupId)
+ .setGroupName("test-group")
+ .setBuckets(new BucketsBuilder().build())
+ .build();
+
+ private final KeyedInstanceIdentifier<Node, NodeKey> nodePath = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, s1Key);
+ private final InstanceIdentifier<FlowCapableNode> flowCapableNodePath = nodePath
+ .augmentation(FlowCapableNode.class);
+ private final InstanceIdentifier<Group> groupPath = flowCapableNodePath.child(Group.class, groupKey);
+
+ @Mock
+ private SalGroupService salGroupService;
+ @Captor
+ private ArgumentCaptor<AddGroupInput> addGroupInputCpt;
+ @Captor
+ private ArgumentCaptor<RemoveGroupInput> removeGroupInputCpt;
+ @Captor
+ private ArgumentCaptor<UpdateGroupInput> updateGroupInputCpt;
+
+ private TransactionId txId;
+
+ private GroupForwarder groupForwarder;
+
+ @Before
+ public void setUp() throws Exception {
+ groupForwarder = new GroupForwarder(salGroupService);
+ txId = new TransactionId(BigInteger.ONE);
+ }
+
+ @Test
+ public void testRemove() throws Exception {
+ Mockito.when(salGroupService.removeGroup(removeGroupInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(
+ new RemoveGroupOutputBuilder()
+ .setTransactionId(txId)
+ .build())
+ .buildFuture()
+ );
+
+ final Future<RpcResult<RemoveGroupOutput>> addResult = groupForwarder.remove(groupPath, group, flowCapableNodePath);
+
+ Mockito.verify(salGroupService).removeGroup(Matchers.<RemoveGroupInput>any());
+
+ Assert.assertTrue(addResult.isDone());
+ final RpcResult<RemoveGroupOutput> result = addResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(result.isSuccessful());
+
+ Assert.assertEquals(1, result.getResult().getTransactionId().getValue().intValue());
+
+ final RemoveGroupInput removeGroupInput = removeGroupInputCpt.getValue();
+ Assert.assertEquals(groupPath, removeGroupInput.getGroupRef().getValue());
+ Assert.assertNull(removeGroupInput.getBuckets());
+ Assert.assertEquals(nodePath, removeGroupInput.getNode().getValue());
+ Assert.assertEquals("test-group", removeGroupInput.getGroupName());
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ Mockito.when(salGroupService.updateGroup(updateGroupInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(
+ new UpdateGroupOutputBuilder()
+ .setTransactionId(txId)
+ .build())
+ .buildFuture()
+ );
+
+ Group groupOriginal = new GroupBuilder(group).build();
+ Group groupUpdate = new GroupBuilder(group)
+ .setGroupName("another-test")
+ .build();
+
+ final Future<RpcResult<UpdateGroupOutput>> addResult = groupForwarder.update(groupPath, groupOriginal, groupUpdate,
+ flowCapableNodePath);
+
+ Mockito.verify(salGroupService).updateGroup(Matchers.<UpdateGroupInput>any());
+
+ Assert.assertTrue(addResult.isDone());
+ final RpcResult<UpdateGroupOutput> result = addResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(result.isSuccessful());
+
+ Assert.assertEquals(1, result.getResult().getTransactionId().getValue().intValue());
+
+ final UpdateGroupInput updateGroupInput = updateGroupInputCpt.getValue();
+ Assert.assertEquals(groupPath, updateGroupInput.getGroupRef().getValue());
+ Assert.assertEquals(nodePath, updateGroupInput.getNode().getValue());
+ Assert.assertNotNull(updateGroupInput.getOriginalGroup().getBuckets());
+ Assert.assertNotNull(updateGroupInput.getUpdatedGroup().getBuckets());
+
+ Assert.assertEquals("test-group", updateGroupInput.getOriginalGroup().getGroupName());
+ Assert.assertEquals("another-test", updateGroupInput.getUpdatedGroup().getGroupName());
+ }
+
+ @Test
+ public void testAdd() throws Exception {
+ Mockito.when(salGroupService.addGroup(addGroupInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(
+ new AddGroupOutputBuilder()
+ .setTransactionId(txId)
+ .build())
+ .buildFuture()
+ );
+
+ final Future<RpcResult<AddGroupOutput>> addResult = groupForwarder.add(groupPath, group, flowCapableNodePath);
+
+ Mockito.verify(salGroupService).addGroup(Matchers.<AddGroupInput>any());
+
+ Assert.assertTrue(addResult.isDone());
+ final RpcResult<AddGroupOutput> result = addResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(result.isSuccessful());
+
+ Assert.assertEquals(1, result.getResult().getTransactionId().getValue().intValue());
+
+ final AddGroupInput addGroupInput = addGroupInputCpt.getValue();
+ Assert.assertEquals(groupPath, addGroupInput.getGroupRef().getValue());
+ Assert.assertEquals(nodePath, addGroupInput.getNode().getValue());
+ Assert.assertNotNull(addGroupInput.getBuckets());
+ Assert.assertEquals("test-group", addGroupInput.getGroupName());
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import java.math.BigInteger;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link MeterForwarder}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class MeterForwarderTest {
+
+ private final NodeKey s1Key = new NodeKey(new NodeId("S1"));
+ private final MeterId meterId = new MeterId(42L);
+ private final MeterKey meterKey = new MeterKey(meterId);
+ private final Meter meter = new MeterBuilder()
+ .setMeterId(meterId)
+ .setMeterName("test-meter")
+ .build();
+
+ private final KeyedInstanceIdentifier<Node, NodeKey> nodePath = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, s1Key);
+ private final InstanceIdentifier<FlowCapableNode> flowCapableNodePath = nodePath
+ .augmentation(FlowCapableNode.class);
+ private final InstanceIdentifier<Meter> meterPath = flowCapableNodePath.child(Meter.class, meterKey);
+
+ @Mock
+ private SalMeterService salMeterService;
+ @Captor
+ private ArgumentCaptor<AddMeterInput> addMeterInputCpt;
+ @Captor
+ private ArgumentCaptor<RemoveMeterInput> removeMeterInputCpt;
+ @Captor
+ private ArgumentCaptor<UpdateMeterInput> updateMeterInputCpt;
+
+ private TransactionId txId;
+
+ private MeterForwarder meterForwarder;
+
+ @Before
+ public void setUp() throws Exception {
+ meterForwarder = new MeterForwarder(salMeterService);
+ txId = new TransactionId(BigInteger.ONE);
+ }
+
+ @Test
+ public void testRemove() throws Exception {
+ Mockito.when(salMeterService.removeMeter(removeMeterInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(new RemoveMeterOutputBuilder()
+ .setTransactionId(txId)
+ .build()).buildFuture()
+ );
+
+ Meter removeMeter = new MeterBuilder(meter).build();
+
+ final Future<RpcResult<RemoveMeterOutput>> removeResult = meterForwarder.remove(meterPath, removeMeter, flowCapableNodePath);
+ Mockito.verify(salMeterService).removeMeter(Matchers.<RemoveMeterInput>any());
+
+ Assert.assertTrue(removeResult.isDone());
+ final RpcResult<RemoveMeterOutput> meterResult = removeResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(meterResult.isSuccessful());
+
+ Assert.assertEquals(1, meterResult.getResult().getTransactionId().getValue().intValue());
+
+ final RemoveMeterInput removeMeterInput = removeMeterInputCpt.getValue();
+ Assert.assertEquals(meterPath, removeMeterInput.getMeterRef().getValue());
+ Assert.assertEquals(nodePath, removeMeterInput.getNode().getValue());
+ Assert.assertEquals("test-meter", removeMeterInput.getMeterName());
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ Mockito.when(salMeterService.updateMeter(updateMeterInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(new UpdateMeterOutputBuilder()
+ .setTransactionId(txId)
+ .build()).buildFuture()
+ );
+
+ Meter meterOriginal = new MeterBuilder(meter).build();
+ Meter meterUpdate = new MeterBuilder(meter)
+ .setMeterName("another-test")
+ .build();
+
+ final Future<RpcResult<UpdateMeterOutput>> updateResult = meterForwarder.update(meterPath, meterOriginal, meterUpdate,
+ flowCapableNodePath);
+ Mockito.verify(salMeterService).updateMeter(Matchers.<UpdateMeterInput>any());
+
+ Assert.assertTrue(updateResult.isDone());
+ final RpcResult<UpdateMeterOutput> meterResult = updateResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(meterResult.isSuccessful());
+
+ Assert.assertEquals(1, meterResult.getResult().getTransactionId().getValue().intValue());
+
+ final UpdateMeterInput updateMeterInput = updateMeterInputCpt.getValue();
+ Assert.assertEquals(meterPath, updateMeterInput.getMeterRef().getValue());
+ Assert.assertEquals(nodePath, updateMeterInput.getNode().getValue());
+
+ Assert.assertEquals("test-meter", updateMeterInput.getOriginalMeter().getMeterName());
+ Assert.assertEquals("another-test", updateMeterInput.getUpdatedMeter().getMeterName());
+ }
+
+ @Test
+ public void testAdd() throws Exception {
+ Mockito.when(salMeterService.addMeter(addMeterInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(new AddMeterOutputBuilder()
+ .setTransactionId(txId)
+ .build()).buildFuture()
+ );
+
+ final Future<RpcResult<AddMeterOutput>> addResult = meterForwarder.add(meterPath, meter, flowCapableNodePath);
+ Mockito.verify(salMeterService).addMeter(Matchers.<AddMeterInput>any());
+
+ Assert.assertTrue(addResult.isDone());
+ final RpcResult<AddMeterOutput> meterResult = addResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(meterResult.isSuccessful());
+
+ Assert.assertEquals(1, meterResult.getResult().getTransactionId().getValue().intValue());
+
+ final AddMeterInput addMeterInput = addMeterInputCpt.getValue();
+ Assert.assertEquals(meterPath, addMeterInput.getMeterRef().getValue());
+ Assert.assertEquals(nodePath, addMeterInput.getNode().getValue());
+ Assert.assertEquals("test-meter", addMeterInput.getMeterName());
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeCachedDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeOdlDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeSnapshotDao;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link SimplifiedConfigListener}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SimplifiedConfigListenerTest {
+
+ private static final NodeId NODE_ID = new NodeId("testNode");
+ private InstanceIdentifier<FlowCapableNode> fcNodePath;
+ private SimplifiedConfigListener nodeListenerConfig;
+ private LogicalDatastoreType dsType = LogicalDatastoreType.CONFIGURATION;
+
+ @Mock
+ private SyncReactor reactor;
+ @Mock
+ private ReadOnlyTransaction roTx;
+ @Mock
+ private DataTreeModification<FlowCapableNode> dataTreeModification;
+ @Mock
+ private DataObjectModification<FlowCapableNode> configModification;
+ @Mock
+ private FlowCapableNode dataBefore;
+ @Mock
+ private FlowCapableNode dataAfter;
+
+ @Before
+ public void setUp() throws Exception {
+ final DataBroker db = Mockito.mock(DataBroker.class);
+ final FlowCapableNodeSnapshotDao configSnapshot = new FlowCapableNodeSnapshotDao();
+ final FlowCapableNodeSnapshotDao operationalSnapshot = new FlowCapableNodeSnapshotDao();
+ final FlowCapableNodeDao operationalDao = new FlowCapableNodeCachedDao(operationalSnapshot,
+ new FlowCapableNodeOdlDao(db, LogicalDatastoreType.OPERATIONAL));
+
+ nodeListenerConfig = new SimplifiedConfigListener(reactor, configSnapshot, operationalDao);
+ fcNodePath = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(NODE_ID))
+ .augmentation(FlowCapableNode.class);
+
+ final DataTreeIdentifier<FlowCapableNode> dataTreeIdentifier =
+ new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, fcNodePath);
+
+ Mockito.when(db.newReadOnlyTransaction()).thenReturn(roTx);
+ Mockito.when(dataTreeModification.getRootPath()).thenReturn(dataTreeIdentifier);
+ Mockito.when(dataTreeModification.getRootNode()).thenReturn(configModification);
+ Mockito.when(reactor.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenReturn(Futures.immediateFuture(Boolean.TRUE));
+ }
+
+ @Test
+ public void testDSLogicalType() throws Exception {
+ Assert.assertEquals(LogicalDatastoreType.CONFIGURATION, nodeListenerConfig.dsType());
+ }
+
+ @Test
+ public void testOnDataTreeChangedSyncupAdd() throws InterruptedException {
+ Mockito.when(roTx.read(LogicalDatastoreType.OPERATIONAL, fcNodePath))
+ .thenReturn(Futures.immediateCheckedFuture(Optional.of(dataBefore)));
+ Mockito.when(configModification.getDataAfter()).thenReturn(dataAfter);
+
+ nodeListenerConfig.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verify(reactor).syncup(fcNodePath, dataAfter, dataBefore, dsType);
+ Mockito.verifyNoMoreInteractions(reactor);
+ Mockito.verify(roTx).close();
+ }
+
+ @Test
+ public void testOnDataTreeChangedSyncupUpdate() throws InterruptedException {
+ Mockito.when(roTx.read(LogicalDatastoreType.OPERATIONAL, fcNodePath))
+ .thenReturn(Futures.immediateCheckedFuture(Optional.of(dataBefore)));
+ Mockito.when(configModification.getDataBefore()).thenReturn(dataBefore);
+ Mockito.when(configModification.getDataAfter()).thenReturn(dataAfter);
+
+ nodeListenerConfig.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verify(reactor).syncup(fcNodePath, dataAfter, dataBefore, dsType);
+ Mockito.verifyNoMoreInteractions(reactor);
+ Mockito.verify(roTx).close();
+ }
+
+ @Test
+ public void testOnDataTreeChangedSyncupDelete() throws InterruptedException {
+ Mockito.when(roTx.read(LogicalDatastoreType.OPERATIONAL, fcNodePath))
+ .thenReturn(Futures.immediateCheckedFuture(Optional.of(dataBefore)));
+ Mockito.when(configModification.getDataBefore()).thenReturn(dataBefore);
+
+ nodeListenerConfig.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verify(reactor).syncup(fcNodePath, null, dataBefore, dsType);
+ Mockito.verifyNoMoreInteractions(reactor);
+ Mockito.verify(roTx).close();
+ }
+
+ @Test
+ public void testOnDataTreeChangedSkip() {
+ Mockito.when(roTx.read(LogicalDatastoreType.OPERATIONAL, fcNodePath)).
+ thenReturn(Futures.immediateCheckedFuture(Optional.absent()));
+
+ nodeListenerConfig.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verifyZeroInteractions(reactor);
+ Mockito.verify(roTx).close();
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeCachedDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeOdlDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeSnapshotDao;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link SimplifiedOperationalListener}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SimplifiedOperationalListenerTest {
+
+ private static final NodeId NODE_ID = new NodeId("testNode");
+ private InstanceIdentifier<FlowCapableNode> fcNodePath;
+ private SimplifiedOperationalListener nodeListenerOperational;
+ private final LogicalDatastoreType dsType = LogicalDatastoreType.OPERATIONAL;
+
+ @Mock
+ private SyncReactor reactor;
+ @Mock
+ private ReadOnlyTransaction roTx;
+ @Mock
+ private DataTreeModification<Node> dataTreeModification;
+ @Mock
+ private DataObjectModification<Node> operationalModification;
+ @Mock
+ private FlowCapableNode configNode;
+ @Mock
+ private Node operationalNode;
+ @Mock
+ private FlowCapableNode fcOperationalNode;
+
+ @Before
+ public void setUp() throws Exception {
+ final DataBroker db = Mockito.mock(DataBroker.class);
+ final FlowCapableNodeSnapshotDao configSnapshot = new FlowCapableNodeSnapshotDao();
+ final FlowCapableNodeSnapshotDao operationalSnapshot = new FlowCapableNodeSnapshotDao();
+ final FlowCapableNodeDao configDao = new FlowCapableNodeCachedDao(configSnapshot,
+ new FlowCapableNodeOdlDao(db, LogicalDatastoreType.CONFIGURATION));
+
+ nodeListenerOperational = new SimplifiedOperationalListener(reactor, operationalSnapshot, configDao);
+ InstanceIdentifier<Node> nodePath = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(NODE_ID));
+ fcNodePath = nodePath.augmentation(FlowCapableNode.class);
+
+ final DataTreeIdentifier<Node> dataTreeIdentifier =
+ new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, nodePath);
+
+ Mockito.when(db.newReadOnlyTransaction()).thenReturn(roTx);
+ Mockito.when(operationalNode.getId()).thenReturn(NODE_ID);
+ Mockito.when(dataTreeModification.getRootPath()).thenReturn(dataTreeIdentifier);
+ Mockito.when(dataTreeModification.getRootNode()).thenReturn(operationalModification);
+ Mockito.when(operationalNode.getAugmentation(FlowCapableNode.class)).thenReturn(fcOperationalNode);
+ }
+
+ @Test
+ public void testDSLogicalType() throws Exception {
+ Assert.assertEquals(LogicalDatastoreType.OPERATIONAL, nodeListenerOperational.dsType());
+ }
+
+ @Test
+ public void testOnDataTreeChangedSyncupAdd() throws InterruptedException {
+ Mockito.when(roTx.read(LogicalDatastoreType.CONFIGURATION, fcNodePath))
+ .thenReturn(Futures.immediateCheckedFuture(Optional.of(configNode)));
+ Mockito.when(reactor.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenReturn(Futures.immediateFuture(Boolean.TRUE));
+ Mockito.when(operationalModification.getDataAfter()).thenReturn(operationalNode);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verify(reactor).syncup(fcNodePath, configNode, fcOperationalNode, dsType);
+ Mockito.verifyNoMoreInteractions(reactor);
+ Mockito.verify(roTx).close();
+ }
+
+ @Test
+ public void testOnDataTreeChangedAddSkip() {
+ // Related to bug 5920 -> https://bugs.opendaylight.org/show_bug.cgi?id=5920
+ Mockito.when(roTx.read(LogicalDatastoreType.CONFIGURATION, fcNodePath))
+ .thenReturn(Futures.immediateCheckedFuture(Optional.absent()));
+ Mockito.when(operationalModification.getDataAfter()).thenReturn(operationalNode);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verifyZeroInteractions(reactor);
+ Mockito.verify(roTx).close();
+ }
+
+ @Test
+ public void testOnDataTreeChangedSyncupDeletePhysical() {
+ Mockito.when(operationalModification.getDataBefore()).thenReturn(operationalNode);
+ Mockito.when(dataTreeModification.getRootNode().getModificationType()).thenReturn(ModificationType.DELETE);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verifyZeroInteractions(reactor);
+ }
+
+ @Test
+ public void testOnDataTreeChangedSyncupDeleteLogical() {
+ Mockito.when(operationalModification.getDataBefore()).thenReturn(operationalNode);
+ List<NodeConnector> nodeConnectorList = Mockito.mock(List.class);
+ Mockito.when(operationalNode.getNodeConnector()).thenReturn(nodeConnectorList);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verifyZeroInteractions(reactor);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncReactor;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeCachedDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeOdlDao;
+import org.opendaylight.openflowplugin.applications.frsync.dao.FlowCapableNodeSnapshotDao;
+import org.opendaylight.openflowplugin.applications.frsync.util.RetryRegistry;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.DateAndTime;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableStatisticsGatheringStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.snapshot.gathering.status.grouping.SnapshotGatheringStatusEnd;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link SimplifiedOperationalRetryListener}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SimplifiedOperationalRetryListenerTest {
+
+ private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(RetryRegistry.DATE_AND_TIME_FORMAT);
+ private static final NodeId NODE_ID = new NodeId("testNode");
+ private InstanceIdentifier<FlowCapableNode> fcNodePath;
+ private SimplifiedOperationalRetryListener nodeListenerOperational;
+ private final String timestampBefore = "0000-12-12T01:01:01.000-07:00";
+ private final String timestampAfter = "9999-12-12T01:01:01.000-07:00";
+ private final LogicalDatastoreType dsType = LogicalDatastoreType.OPERATIONAL;
+
+ @Mock
+ private SyncReactor reactor;
+ @Mock
+ private ReadOnlyTransaction roTx;
+ @Mock
+ private DataTreeModification<Node> dataTreeModification;
+ @Mock
+ private DataObjectModification<Node> operationalModification;
+ @Mock
+ private FlowCapableNode configNode;
+ @Mock
+ private Node operationalNode;
+ @Mock
+ private FlowCapableNode fcOperationalNode;
+ @Mock
+ private RetryRegistry retryRegistry;
+ @Mock
+ private FlowCapableStatisticsGatheringStatus statisticsGatheringStatus;
+ @Mock
+ private SnapshotGatheringStatusEnd snapshotGatheringStatusEnd;
+
+ @Before
+ public void setUp() throws Exception {
+ final DataBroker db = Mockito.mock(DataBroker.class);
+ final FlowCapableNodeSnapshotDao configSnapshot = new FlowCapableNodeSnapshotDao();
+ final FlowCapableNodeSnapshotDao operationalSnapshot = new FlowCapableNodeSnapshotDao();
+ final FlowCapableNodeDao configDao = new FlowCapableNodeCachedDao(configSnapshot,
+ new FlowCapableNodeOdlDao(db, LogicalDatastoreType.CONFIGURATION));
+
+ nodeListenerOperational = new SimplifiedOperationalRetryListener(reactor, operationalSnapshot, configDao, retryRegistry);
+ InstanceIdentifier<Node> nodePath = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(NODE_ID));
+ fcNodePath = nodePath.augmentation(FlowCapableNode.class);
+
+ final DataTreeIdentifier<Node> dataTreeIdentifier =
+ new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, nodePath);
+
+ Mockito.when(db.newReadOnlyTransaction()).thenReturn(roTx);
+ Mockito.when(operationalNode.getId()).thenReturn(NODE_ID);
+ Mockito.when(dataTreeModification.getRootPath()).thenReturn(dataTreeIdentifier);
+ Mockito.when(dataTreeModification.getRootNode()).thenReturn(operationalModification);
+ Mockito.when(operationalNode.getAugmentation(FlowCapableNode.class)).thenReturn(fcOperationalNode);
+ }
+
+ @Test
+ public void testOnDataTreeChangedRetryNotRegistered() {
+ Mockito.when(operationalModification.getDataBefore()).thenReturn(operationalNode);
+ Mockito.when(operationalModification.getDataAfter()).thenReturn(operationalNode);
+ Mockito.when(retryRegistry.isRegistered(NODE_ID)).thenReturn(false);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verifyZeroInteractions(reactor);
+ }
+
+ @Test
+ public void testOnDataTreeChangedRetryButStaticsGatheringNotStarted() {
+ Mockito.when(operationalModification.getDataBefore()).thenReturn(operationalNode);
+ Mockito.when(operationalModification.getDataAfter()).thenReturn(operationalNode);
+ Mockito.when(retryRegistry.isRegistered(NODE_ID)).thenReturn(true);
+ Mockito.when(operationalNode.getAugmentation(FlowCapableStatisticsGatheringStatus.class)).thenReturn(null);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verifyZeroInteractions(reactor);
+ }
+
+ @Test
+ public void testOnDataTreeChangedRetryButStaticsGatheringNotFinished() {
+ Mockito.when(operationalModification.getDataBefore()).thenReturn(operationalNode);
+ Mockito.when(operationalModification.getDataAfter()).thenReturn(operationalNode);
+ Mockito.when(retryRegistry.isRegistered(NODE_ID)).thenReturn(true);
+ Mockito.when(operationalNode.getAugmentation(FlowCapableStatisticsGatheringStatus.class)).thenReturn(statisticsGatheringStatus);
+ Mockito.when(statisticsGatheringStatus.getSnapshotGatheringStatusEnd()).thenReturn(null);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verifyZeroInteractions(reactor);
+ }
+
+ @Test
+ public void testOnDataTreeChangedRetryButStaticsGatheringNotSuccessful() {
+ Mockito.when(operationalModification.getDataBefore()).thenReturn(operationalNode);
+ Mockito.when(operationalModification.getDataAfter()).thenReturn(operationalNode);
+ Mockito.when(retryRegistry.isRegistered(NODE_ID)).thenReturn(true);
+ Mockito.when(operationalNode.getAugmentation(FlowCapableStatisticsGatheringStatus.class)).thenReturn(statisticsGatheringStatus);
+ Mockito.when(statisticsGatheringStatus.getSnapshotGatheringStatusEnd()).thenReturn(snapshotGatheringStatusEnd);
+ Mockito.when(snapshotGatheringStatusEnd.isSucceeded()).thenReturn(false);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verifyZeroInteractions(reactor);
+ }
+
+ @Test
+ public void testOnDataTreeChangedRetryAndFreshOperationalNotPresent() throws ParseException {
+ final DateAndTime timestamp = Mockito.mock(DateAndTime.class);
+ Mockito.when(operationalModification.getDataBefore()).thenReturn(operationalNode);
+ Mockito.when(operationalModification.getDataAfter()).thenReturn(operationalNode);
+ Mockito.when(retryRegistry.isRegistered(NODE_ID)).thenReturn(true);
+ Mockito.when(operationalNode.getAugmentation(FlowCapableStatisticsGatheringStatus.class)).thenReturn(statisticsGatheringStatus);
+ Mockito.when(statisticsGatheringStatus.getSnapshotGatheringStatusEnd()).thenReturn(snapshotGatheringStatusEnd);
+ Mockito.when(snapshotGatheringStatusEnd.isSucceeded()).thenReturn(true);
+ Mockito.when(snapshotGatheringStatusEnd.getEnd()).thenReturn(timestamp);
+ Mockito.when(snapshotGatheringStatusEnd.getEnd().getValue()).thenReturn(timestampBefore);
+ Mockito.when(retryRegistry.getRegistration(NODE_ID)).thenReturn(simpleDateFormat.parse(timestampAfter));
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verifyZeroInteractions(reactor);
+ }
+
+ @Test
+ public void testOnDataTreeChangedRetryAndFreshOperationalPresent() throws Exception {
+ final DateAndTime timestamp = Mockito.mock(DateAndTime.class);
+ Mockito.when(roTx.read(LogicalDatastoreType.CONFIGURATION, fcNodePath))
+ .thenReturn(Futures.immediateCheckedFuture(Optional.of(configNode)));
+ Mockito.when(reactor.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenReturn(Futures.immediateFuture(Boolean.TRUE));
+ Mockito.when(operationalModification.getDataBefore()).thenReturn(operationalNode);
+ Mockito.when(operationalModification.getDataAfter()).thenReturn(operationalNode);
+ Mockito.when(retryRegistry.isRegistered(NODE_ID)).thenReturn(true);
+ Mockito.when(operationalNode.getAugmentation(FlowCapableStatisticsGatheringStatus.class)).thenReturn(statisticsGatheringStatus);
+ Mockito.when(statisticsGatheringStatus.getSnapshotGatheringStatusEnd()).thenReturn(snapshotGatheringStatusEnd);
+ Mockito.when(snapshotGatheringStatusEnd.isSucceeded()).thenReturn(true);
+ Mockito.when(snapshotGatheringStatusEnd.getEnd()).thenReturn(timestamp);
+ Mockito.when(snapshotGatheringStatusEnd.getEnd().getValue()).thenReturn(timestampAfter);
+ Mockito.when(retryRegistry.getRegistration(NODE_ID)).thenReturn(simpleDateFormat.parse(timestampBefore));
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verify(reactor).syncup(fcNodePath, configNode, fcOperationalNode, dsType);
+ Mockito.verifyNoMoreInteractions(reactor);
+ Mockito.verify(roTx).close();
+ }
+
+ @Test
+ public void testOnDataTreeChangedRetryAndNodeDeleted() {
+ Mockito.when(operationalModification.getDataBefore()).thenReturn(operationalNode);
+ Mockito.when(dataTreeModification.getRootNode().getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
+
+ nodeListenerOperational.onDataTreeChanged(Collections.singleton(dataTreeModification));
+
+ Mockito.verify(retryRegistry).unregisterIfRegistered(NODE_ID);
+ Mockito.verifyZeroInteractions(reactor);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test for {@link SyncReactorFutureZipDecorator}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SyncReactorFutureZipDecoratorTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncReactorFutureZipDecoratorTest.class);
+ private static final NodeId NODE_ID = new NodeId("testNode");
+ private SyncReactorFutureZipDecorator reactor;
+ private InstanceIdentifier<FlowCapableNode> fcNodePath;
+ private ListeningExecutorService syncThreadPool;
+
+ @Mock
+ private SyncReactorGuardDecorator delegate;
+
+ @Before
+ public void setUp() {
+ syncThreadPool = FrmExecutors.instance()
+ .newFixedThreadPool(1, new ThreadFactoryBuilder()
+ .setNameFormat(SyncReactorFutureDecorator.FRM_RPC_CLIENT_PREFIX + "%d")
+ .setDaemon(false)
+ .build());
+
+ reactor = new SyncReactorFutureZipDecorator(delegate, syncThreadPool);
+ fcNodePath = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(NODE_ID))
+ .augmentation(FlowCapableNode.class);
+ }
+
+ @Test
+ public void testSyncupWithOptimizedConfigDeltaCompression() throws Exception {
+ final FlowCapableNode dataBefore = Mockito.mock(FlowCapableNode.class);
+ final FlowCapableNode dataAfter = Mockito.mock(FlowCapableNode.class);
+ final FlowCapableNode dataAfter2 = Mockito.mock(FlowCapableNode.class);
+ final CountDownLatch latchForFirst = new CountDownLatch(1);
+ final CountDownLatch latchForNext = new CountDownLatch(1);
+ final LogicalDatastoreType dsType = LogicalDatastoreType.CONFIGURATION;
+
+ Mockito.when(delegate.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenAnswer(new Answer<ListenableFuture<Boolean>>() {
+ @Override
+ public ListenableFuture<Boolean> answer(final InvocationOnMock invocationOnMock) throws Throwable {
+ LOG.info("unlocking next configs");
+ latchForNext.countDown();
+ latchForFirst.await();
+ LOG.info("unlocking first delegate");
+ return Futures.immediateFuture(Boolean.TRUE);
+ }
+ }).thenReturn(Futures.immediateFuture(Boolean.TRUE));
+
+ final List<ListenableFuture<Boolean>> allResults = new ArrayList<>();
+ allResults.add(reactor.syncup(fcNodePath, dataBefore, null, dsType));
+ latchForNext.await();
+
+ allResults.add(reactor.syncup(fcNodePath, dataAfter, dataBefore, dsType));
+ allResults.add(reactor.syncup(fcNodePath, null, dataAfter, dsType));
+ allResults.add(reactor.syncup(fcNodePath, dataAfter2, null, dsType));
+ latchForFirst.countDown();
+
+ Futures.allAsList(allResults).get(1, TimeUnit.SECONDS);
+ LOG.info("all configs done");
+
+ syncThreadPool.shutdown();
+ boolean terminated = syncThreadPool.awaitTermination(1, TimeUnit.SECONDS);
+ if (!terminated) {
+ LOG.info("thread pool not terminated.");
+ syncThreadPool.shutdownNow();
+ }
+ final InOrder inOrder = Mockito.inOrder(delegate);
+ inOrder.verify(delegate).syncup(fcNodePath, dataBefore, null, dsType);
+ inOrder.verify(delegate).syncup(fcNodePath, dataAfter2, dataBefore, dsType);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testSyncupConfigEmptyQueue() throws Exception {
+ final FlowCapableNode dataBefore = Mockito.mock(FlowCapableNode.class);
+ final FlowCapableNode dataAfter = Mockito.mock(FlowCapableNode.class);
+ final CountDownLatch latchForNext = new CountDownLatch(1);
+ final LogicalDatastoreType dsType = LogicalDatastoreType.CONFIGURATION;
+
+ Mockito.when(delegate.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenAnswer(new Answer<ListenableFuture<Boolean>>() {
+ @Override
+ public ListenableFuture<Boolean> answer(final InvocationOnMock invocationOnMock) throws Throwable {
+ LOG.info("unlocking next config");
+ latchForNext.countDown();
+ return Futures.immediateFuture(Boolean.TRUE);
+ }
+ }).thenReturn(Futures.immediateFuture(Boolean.TRUE));
+
+ reactor.syncup(fcNodePath, dataBefore, null, dsType);
+ latchForNext.await();
+ reactor.syncup(fcNodePath, dataAfter, dataBefore, dsType);
+
+ boolean terminated = syncThreadPool.awaitTermination(1, TimeUnit.SECONDS);
+ if (!terminated) {
+ LOG.info("thread pool not terminated.");
+ syncThreadPool.shutdownNow();
+ }
+ final InOrder inOrder = Mockito.inOrder(delegate);
+ inOrder.verify(delegate).syncup(fcNodePath, dataBefore, null, dsType);
+ inOrder.verify(delegate).syncup(fcNodePath, dataAfter, dataBefore, dsType);
+ inOrder.verifyNoMoreInteractions();
+
+ }
+
+ @Test
+ public void testSyncupRewriteZipEntryWithOperationalDelta() throws Exception {
+ final FlowCapableNode configBefore = Mockito.mock(FlowCapableNode.class);
+ final FlowCapableNode configAfter = Mockito.mock(FlowCapableNode.class);
+ final FlowCapableNode configActual = Mockito.mock(FlowCapableNode.class);
+ final FlowCapableNode freshOperational = Mockito.mock(FlowCapableNode.class);
+ final CountDownLatch latchForFirst = new CountDownLatch(1);
+ final CountDownLatch latchForNext = new CountDownLatch(1);
+
+ Mockito.when(delegate.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenAnswer(new Answer<ListenableFuture<Boolean>>() {
+ @Override
+ public ListenableFuture<Boolean> answer(final InvocationOnMock invocationOnMock) throws Throwable {
+ LOG.info("unlocking for fresh operational");
+ latchForNext.countDown();
+ latchForFirst.await();
+ LOG.info("unlocking first delegate");
+ return Futures.immediateFuture(Boolean.TRUE);
+ }
+ }).thenReturn(Futures.immediateFuture(Boolean.TRUE));
+
+ reactor.syncup(fcNodePath, configAfter, configBefore, LogicalDatastoreType.CONFIGURATION);
+ latchForNext.await();
+
+ reactor.syncup(fcNodePath, configActual, freshOperational, LogicalDatastoreType.OPERATIONAL);
+ latchForFirst.countDown();
+
+ syncThreadPool.shutdown();
+ boolean terminated = syncThreadPool.awaitTermination(1, TimeUnit.SECONDS);
+ if (!terminated) {
+ LOG.info("thread pool not terminated.");
+ syncThreadPool.shutdownNow();
+ }
+ Mockito.verify(delegate, Mockito.times(1)).syncup(fcNodePath, configActual, freshOperational, LogicalDatastoreType.OPERATIONAL);
+ }
+
+ @After
+ public void tearDown() {
+ syncThreadPool.shutdownNow();
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.util.SemaphoreKeeperGuavaImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link SyncReactorGuardDecorator}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SyncReactorGuardDecoratorTest {
+
+ private static final NodeId NODE_ID = new NodeId("test-node");
+ private SyncReactorGuardDecorator reactor;
+ private InstanceIdentifier<FlowCapableNode> fcNodePath;
+ private final LogicalDatastoreType dsType = LogicalDatastoreType.CONFIGURATION;
+
+ @Mock
+ private SyncReactorRetryDecorator delegate;
+ @Mock
+ private FlowCapableNode fcConfigNode;
+ @Mock
+ private FlowCapableNode fcOperationalNode;
+
+ @Before
+ public void setUp() throws Exception {
+ final SemaphoreKeeperGuavaImpl semaphoreKeeper = new SemaphoreKeeperGuavaImpl<InstanceIdentifier<FlowCapableNode>>(1, true);
+ reactor = new SyncReactorGuardDecorator(delegate, semaphoreKeeper);
+ InstanceIdentifier<Node> nodePath = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(NODE_ID));
+ fcNodePath = nodePath.augmentation(FlowCapableNode.class);
+
+ final Node operationalNode = Mockito.mock(Node.class);
+ Mockito.when(operationalNode.getId()).thenReturn(NODE_ID);
+ Mockito.when(operationalNode.getAugmentation(FlowCapableNode.class)).thenReturn(fcOperationalNode);
+ }
+
+ @Test
+ public void testSyncupSuccess() throws Exception {
+ Mockito.when(delegate.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenReturn(Futures.immediateFuture(Boolean.TRUE));
+
+ reactor.syncup(fcNodePath, fcConfigNode, fcOperationalNode, dsType);
+
+ Mockito.verify(delegate).syncup(fcNodePath, fcConfigNode, fcOperationalNode, dsType);
+ Mockito.verifyNoMoreInteractions(delegate);
+ }
+
+ @Test
+ public void testSyncupFail() throws Exception {
+ Mockito.when(delegate.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenReturn(Futures.immediateFailedFuture(new Exception()));
+
+ reactor.syncup(fcNodePath, fcConfigNode, fcOperationalNode, dsType);
+
+ Mockito.verify(delegate).syncup(fcNodePath, fcConfigNode, fcOperationalNode, dsType);
+ Mockito.verifyNoMoreInteractions(delegate);
+
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.SyncPlanPushStrategy;
+import org.opendaylight.openflowplugin.applications.frsync.impl.strategy.SynchronizationDiffInput;
+import org.opendaylight.openflowplugin.applications.frsync.util.ReconcileUtil;
+import org.opendaylight.openflowplugin.applications.frsync.util.SyncCrudCounters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test for {@link SyncReactorImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SyncReactorImplTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SyncReactorImplTest.class);
+
+ private static final NodeId NODE_ID = new NodeId("unit-nodeId");
+ private static final InstanceIdentifier<FlowCapableNode> NODE_IDENT = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, new NodeKey(NODE_ID)).augmentation(FlowCapableNode.class);
+ private SyncReactorImpl reactor;
+
+ @Mock
+ private DataBroker db;
+ @Mock
+ private SyncPlanPushStrategy syncPlanPushStrategy;
+ @Captor
+ private ArgumentCaptor<Group> groupCaptor;
+ @Captor
+ private ArgumentCaptor<Group> groupUpdateCaptor;
+ @Captor
+ private ArgumentCaptor<Flow> flowCaptor;
+ @Captor
+ private ArgumentCaptor<Flow> flowUpdateCaptor;
+ @Captor
+ private ArgumentCaptor<Meter> meterCaptor;
+ @Captor
+ private ArgumentCaptor<Meter> meterUpdateCaptor;
+ @Captor
+ private ArgumentCaptor<TableFeatures> tableFeaturesCaptor;
+ @Captor
+ private ArgumentCaptor<SynchronizationDiffInput> syncDiffInputCaptor;
+
+ @Before
+ public void setUp() throws Exception {
+ reactor = new SyncReactorImpl(syncPlanPushStrategy);
+ }
+
+ @Test
+ public void testSyncup() throws Exception {
+ final FlowCapableNode configFcn = new FlowCapableNodeBuilder()
+ .setGroup(Collections.singletonList(DSInputFactory.createGroup(1L)))
+ .setTable(Collections.singletonList(new TableBuilder()
+ .setFlow(Collections.singletonList(DSInputFactory.createFlow("f1", 1)))
+ .build()))
+ .setMeter(Collections.singletonList(DSInputFactory.createMeter(1L)))
+ .build();
+
+ final FlowCapableNode operationalFcn = new FlowCapableNodeBuilder()
+ .setGroup(Collections.singletonList(DSInputFactory.createGroup(2L)))
+ .setTable(Collections.singletonList(new TableBuilder()
+ .setFlow(Collections.singletonList(DSInputFactory.createFlow("f2", 2)))
+ .build()))
+ .setMeter(Collections.singletonList(DSInputFactory.createMeter(2L)))
+ .build();
+
+ Mockito.when(syncPlanPushStrategy.executeSyncStrategy(
+ Matchers.<ListenableFuture<RpcResult<Void>>>any(),
+ Matchers.<SynchronizationDiffInput>any(),
+ Matchers.<SyncCrudCounters>any()))
+ .thenReturn(RpcResultBuilder.<Void>success().buildFuture());
+
+ final ListenableFuture<Boolean> syncupResult = reactor.syncup(NODE_IDENT, configFcn, operationalFcn, LogicalDatastoreType.CONFIGURATION);
+ try {
+ Assert.assertTrue(syncupResult.isDone());
+ final Boolean voidRpcResult = syncupResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(voidRpcResult);
+
+ Mockito.verify(syncPlanPushStrategy).executeSyncStrategy(
+ Matchers.<ListenableFuture<RpcResult<Void>>>any(),
+ syncDiffInputCaptor.capture(),
+ Matchers.<SyncCrudCounters>any()
+ );
+
+ final SynchronizationDiffInput diffInput = syncDiffInputCaptor.getValue();
+ Assert.assertEquals(1, ReconcileUtil.countTotalPushed(diffInput.getFlowsToAddOrUpdate().values()));
+ Assert.assertEquals(0, ReconcileUtil.countTotalUpdated(diffInput.getFlowsToAddOrUpdate().values()));
+ Assert.assertEquals(1, ReconcileUtil.countTotalPushed(diffInput.getFlowsToRemove().values()));
+
+ Assert.assertEquals(1, ReconcileUtil.countTotalPushed(diffInput.getGroupsToAddOrUpdate()));
+ Assert.assertEquals(0, ReconcileUtil.countTotalUpdated(diffInput.getGroupsToAddOrUpdate()));
+ Assert.assertEquals(1, ReconcileUtil.countTotalPushed(diffInput.getGroupsToRemove()));
+
+ Assert.assertEquals(1, diffInput.getMetersToAddOrUpdate().getItemsToPush().size());
+ Assert.assertEquals(0, diffInput.getMetersToAddOrUpdate().getItemsToUpdate().size());
+ Assert.assertEquals(1, diffInput.getMetersToRemove().getItemsToPush().size());
+ } catch (Exception e) {
+ LOG.warn("syncup failed", e);
+ Assert.fail("syncup failed: " + e.getMessage());
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.frsync.util.RetryRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Test for {@link SyncReactorRetryDecorator}
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SyncReactorRetryDecoratorTest {
+
+ private static final NodeId NODE_ID = new NodeId("test-node");
+ private SyncReactorRetryDecorator reactor;
+ private InstanceIdentifier<FlowCapableNode> fcNodePath;
+ private final LogicalDatastoreType dsType = LogicalDatastoreType.CONFIGURATION;
+
+ @Mock
+ private SyncReactorImpl delegate;
+ @Mock
+ private RetryRegistry retryRegistry;
+ @Mock
+ private FlowCapableNode fcConfigNode;
+ @Mock
+ private FlowCapableNode fcOperationalNode;
+
+ @Before
+ public void setUp() {
+ reactor = new SyncReactorRetryDecorator(delegate, retryRegistry);
+ InstanceIdentifier<Node> nodePath = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(NODE_ID));
+ fcNodePath = nodePath.augmentation(FlowCapableNode.class);
+
+ final Node operationalNode = Mockito.mock(Node.class);
+ Mockito.when(operationalNode.getId()).thenReturn(NODE_ID);
+ Mockito.when(operationalNode.getAugmentation(FlowCapableNode.class)).thenReturn(fcOperationalNode);
+ }
+
+ @Test
+ public void testSyncupSuccess() throws InterruptedException {
+ Mockito.when(delegate.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenReturn(Futures.immediateFuture(Boolean.TRUE));
+
+ reactor.syncup(fcNodePath, fcConfigNode, fcOperationalNode, dsType);
+
+ Mockito.verify(delegate).syncup(fcNodePath, fcConfigNode, fcOperationalNode, dsType);
+ Mockito.verifyNoMoreInteractions(delegate);
+ Mockito.verify(retryRegistry).unregisterIfRegistered(NODE_ID);
+ }
+
+ @Test
+ public void testSyncupFail() throws InterruptedException {
+ Mockito.when(delegate.syncup(Matchers.<InstanceIdentifier<FlowCapableNode>>any(), Matchers.<FlowCapableNode>any(),
+ Matchers.<FlowCapableNode>any(), Matchers.<LogicalDatastoreType>any())).thenReturn(Futures.immediateFuture(Boolean.FALSE));
+
+ reactor.syncup(fcNodePath, fcConfigNode, fcOperationalNode, dsType);
+
+ Mockito.verify(delegate).syncup(fcNodePath, fcConfigNode, fcOperationalNode, dsType);
+ Mockito.verifyNoMoreInteractions(delegate);
+ Mockito.verify(retryRegistry).register(NODE_ID);
+ }
+
+ @Test
+ public void testSyncupConfigIgnoreInRetry() throws InterruptedException {
+ Mockito.when(retryRegistry.isRegistered(NODE_ID)).thenReturn(true);
+
+ reactor.syncup(fcNodePath, fcConfigNode, fcOperationalNode, dsType);
+
+ Mockito.verifyZeroInteractions(delegate);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl;
+
+import java.math.BigInteger;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link TableForwarder}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class TableForwarderTest {
+
+ private final NodeKey s1Key = new NodeKey(new NodeId("S1"));
+ private final Short tableId = (short) 42;
+ private final TableKey tableKey = new TableKey(tableId);
+ private final TableFeaturesKey tableFeaturesKey = new TableFeaturesKey(tableId);
+ private final TableFeatures tableFeatures = new TableFeaturesBuilder()
+ .setName("test-table")
+ .setTableId(tableId)
+ .build();
+
+ private final KeyedInstanceIdentifier<Node, NodeKey> nodePath = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, s1Key);
+ private final InstanceIdentifier<FlowCapableNode> flowCapableNodePath = nodePath
+ .augmentation(FlowCapableNode.class);
+ private final KeyedInstanceIdentifier<Table, TableKey> tablePath = flowCapableNodePath
+ .child(Table.class, tableKey);
+ private final InstanceIdentifier<TableFeatures> tableFeaturesPath = flowCapableNodePath
+ .child(TableFeatures.class, tableFeaturesKey);
+
+ @Captor
+ private ArgumentCaptor<UpdateTableInput> updateTableInputCpt;
+ @Mock
+ private SalTableService salTableService;
+
+ private TransactionId txId;
+
+ private TableForwarder tableForwarder;
+
+
+ @Before
+ public void setUp() throws Exception {
+ tableForwarder = new TableForwarder(salTableService);
+ txId = new TransactionId(BigInteger.ONE);
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ Mockito.when(salTableService.updateTable(updateTableInputCpt.capture())).thenReturn(
+ RpcResultBuilder.success(
+ new UpdateTableOutputBuilder()
+ .setTransactionId(txId)
+ .build()
+ ).buildFuture()
+ );
+
+ final TableFeatures tableFeaturesUpdate = new TableFeaturesBuilder(tableFeatures)
+ .setName("another-table")
+ .build();
+ final Future<RpcResult<UpdateTableOutput>> updateResult = tableForwarder.update(
+ tableFeaturesPath, tableFeatures, tableFeaturesUpdate, flowCapableNodePath);
+
+ Mockito.verify(salTableService).updateTable(Matchers.<UpdateTableInput>any());
+
+ Assert.assertTrue(updateResult.isDone());
+ final RpcResult<UpdateTableOutput> updateTableResult = updateResult.get(2, TimeUnit.SECONDS);
+ Assert.assertTrue(updateTableResult.isSuccessful());
+
+ Assert.assertEquals(1, updateTableResult.getResult().getTransactionId().getValue().intValue());
+
+ final UpdateTableInput updateTableInput = updateTableInputCpt.getValue();
+ Assert.assertEquals(tablePath, updateTableInput.getTableRef().getValue());
+ Assert.assertEquals(nodePath, updateTableInput.getNode().getValue());
+
+ Assert.assertEquals(1, updateTableInput.getOriginalTable().getTableFeatures().size());
+ Assert.assertEquals("test-table", updateTableInput.getOriginalTable().getTableFeatures().get(0).getName());
+ Assert.assertEquals(1, updateTableInput.getUpdatedTable().getTableFeatures().size());
+ Assert.assertEquals("another-table", updateTableInput.getUpdatedTable().getTableFeatures().get(0).getName());
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl.strategy;
+
+import org.opendaylight.openflowplugin.applications.frsync.util.ItemSyncBox;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+
+/**
+ * Provides create methods for data involved in {@link SynchronizationDiffInput}.
+ */
+public class DiffInputFactory {
+ static ItemSyncBox<Group> createGroupSyncBox(final long... groupIDs) {
+ final ItemSyncBox<Group> groupBox = new ItemSyncBox<>();
+
+ for (long gid : groupIDs) {
+ groupBox.getItemsToPush().add(createPlainGroup(gid));
+ }
+ return groupBox;
+ }
+
+ static ItemSyncBox<Group> createGroupSyncBoxWithUpdates(final long... groupIDs) {
+ final ItemSyncBox<Group> groupBox = new ItemSyncBox<>();
+
+ for (long gid : groupIDs) {
+ groupBox.getItemsToPush().add(createPlainGroup(gid));
+ groupBox.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(createPlainGroup(gid + 50),
+ createPlainGroup(gid + 100)));
+ }
+ return groupBox;
+ }
+
+ private static Group createPlainGroup(final long gid) {
+ return new GroupBuilder().setGroupId(new GroupId(gid)).build();
+ }
+
+ static ItemSyncBox<Meter> createMeterSyncBox(final long... meterIDs) {
+ final ItemSyncBox<Meter> groupBox = new ItemSyncBox<>();
+
+ for (long gid : meterIDs) {
+ groupBox.getItemsToPush().add(createPlainMeter(gid));
+ }
+ return groupBox;
+ }
+
+ static ItemSyncBox<Meter> createMeterSyncBoxWithUpdates(final long... meterIDs) {
+ final ItemSyncBox<Meter> groupBox = new ItemSyncBox<>();
+
+ for (long mid : meterIDs) {
+ groupBox.getItemsToPush().add(createPlainMeter(mid));
+ groupBox.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(createPlainMeter(mid + 50),
+ createPlainMeter(mid + 100)));
+ }
+ return groupBox;
+ }
+
+ private static Meter createPlainMeter(final long mid) {
+ return new MeterBuilder().setMeterId(new MeterId(mid)).build();
+ }
+
+ static ItemSyncBox<Flow> createFlowSyncBox(final String... flowIDs) {
+ final ItemSyncBox<Flow> flowBox = new ItemSyncBox<>();
+
+ for (String fid : flowIDs) {
+ flowBox.getItemsToPush().add(createPlainFlow(fid));
+ }
+ return flowBox;
+ }
+
+ static ItemSyncBox<Flow> createFlowSyncBoxWithUpdates(final String... flowIDs) {
+ final ItemSyncBox<Flow> groupBox = new ItemSyncBox<>();
+
+ for (String fid : flowIDs) {
+ groupBox.getItemsToPush().add(createPlainFlow(fid));
+ groupBox.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(createPlainFlow(fid + "orig"),
+ createPlainFlow(fid + "upd")));
+ }
+ return groupBox;
+ }
+
+ private static Flow createPlainFlow(final String fid) {
+ return new FlowBuilder().setId(new FlowId(fid)).build();
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl.strategy;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Range;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowplugin.applications.frsync.impl.TableForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.util.ItemSyncBox;
+import org.opendaylight.openflowplugin.applications.frsync.util.SyncCrudCounters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.Batch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.BatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddFlowCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddMeterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveFlowCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveMeterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateFlowCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateFlowCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateGroupCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateMeterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateMeterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link SyncPlanPushStrategyFlatBatchImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SyncPlanPushStrategyFlatBatchImplTest {
+
+ private static final NodeId NODE_ID = new NodeId("ut-node-id");
+ private static final InstanceIdentifier<FlowCapableNode> NODE_IDENT = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, new NodeKey(NODE_ID))
+ .augmentation(FlowCapableNode.class);
+ @Mock
+ private SalFlatBatchService flatBatchService;
+ @Mock
+ private TableForwarder tableForwarder;
+ @Captor
+ private ArgumentCaptor<ProcessFlatBatchInput> processFlatBatchInputCpt;
+
+ private List<ItemSyncBox<Group>> groupsToAddOrUpdate;
+ private List<ItemSyncBox<Group>> groupsToRemove;
+ private ItemSyncBox<Meter> metersToAddOrUpdate;
+ private ItemSyncBox<Meter> metersToRemove;
+ private Map<TableKey, ItemSyncBox<Flow>> flowsToAddOrUpdate;
+ private Map<TableKey, ItemSyncBox<Flow>> flowsToRemove;
+ private List<Batch> batchBag;
+
+ private SyncPlanPushStrategyFlatBatchImpl syncPlanPushStrategy;
+
+ public SyncPlanPushStrategyFlatBatchImplTest() {
+ groupsToAddOrUpdate = Lists.newArrayList(DiffInputFactory.createGroupSyncBox(1, 2, 3),
+ DiffInputFactory.createGroupSyncBoxWithUpdates(4, 5, 6));
+ groupsToRemove = Lists.newArrayList(DiffInputFactory.createGroupSyncBox(1, 2, 3),
+ DiffInputFactory.createGroupSyncBox(4, 5, 6));
+
+ metersToAddOrUpdate = DiffInputFactory.createMeterSyncBoxWithUpdates(1, 2, 3);
+ metersToRemove = DiffInputFactory.createMeterSyncBox(1, 2, 3);
+
+ flowsToAddOrUpdate = new HashMap<>();
+ flowsToAddOrUpdate.put(new TableKey((short) 0), DiffInputFactory.createFlowSyncBox("1", "2", "3"));
+ flowsToAddOrUpdate.put(new TableKey((short) 1), DiffInputFactory.createFlowSyncBoxWithUpdates("4", "5", "6"));
+ flowsToRemove = new HashMap<>();
+ flowsToRemove.put(new TableKey((short) 0), DiffInputFactory.createFlowSyncBox("1", "2", "3"));
+ flowsToRemove.put(new TableKey((short) 1), DiffInputFactory.createFlowSyncBox("4", "5", "6"));
+ }
+
+
+ @Before
+ public void setUp() throws Exception {
+ syncPlanPushStrategy = new SyncPlanPushStrategyFlatBatchImpl();
+ syncPlanPushStrategy.setFlatBatchService(flatBatchService);
+ syncPlanPushStrategy.setTableForwarder(tableForwarder);
+
+ batchBag = new ArrayList<>();
+ }
+
+ @Test
+ public void testExecuteSyncStrategy() throws Exception {
+ final SynchronizationDiffInput diffInput = new SynchronizationDiffInput(NODE_IDENT,
+ groupsToAddOrUpdate, metersToAddOrUpdate, flowsToAddOrUpdate, flowsToRemove, metersToRemove, groupsToRemove);
+
+ Mockito.when(flatBatchService.processFlatBatch(Matchers.<ProcessFlatBatchInput>any()))
+ .thenReturn(RpcResultBuilder.success(new ProcessFlatBatchOutputBuilder().build()).buildFuture());
+
+ final SyncCrudCounters counters = new SyncCrudCounters();
+ final ListenableFuture<RpcResult<Void>> rpcResult = syncPlanPushStrategy.executeSyncStrategy(
+ RpcResultBuilder.<Void>success().buildFuture(), diffInput, counters);
+
+ Mockito.verify(flatBatchService).processFlatBatch(processFlatBatchInputCpt.capture());
+
+ final ProcessFlatBatchInput processFlatBatchInput = processFlatBatchInputCpt.getValue();
+ Assert.assertFalse(processFlatBatchInput.isExitOnFirstError());
+ Assert.assertEquals(13, processFlatBatchInput.getBatch().size());
+
+ Assert.assertTrue(rpcResult.isDone());
+ Assert.assertTrue(rpcResult.get().isSuccessful());
+
+ Assert.assertEquals(6, counters.getFlowCrudCounts().getAdded());
+ Assert.assertEquals(3, counters.getFlowCrudCounts().getUpdated());
+ Assert.assertEquals(6, counters.getFlowCrudCounts().getRemoved());
+
+ Assert.assertEquals(6, counters.getGroupCrudCounts().getAdded());
+ Assert.assertEquals(3, counters.getGroupCrudCounts().getUpdated());
+ Assert.assertEquals(6, counters.getGroupCrudCounts().getRemoved());
+
+ Assert.assertEquals(3, counters.getMeterCrudCounts().getAdded());
+ Assert.assertEquals(3, counters.getMeterCrudCounts().getUpdated());
+ Assert.assertEquals(3, counters.getMeterCrudCounts().getRemoved());
+ }
+
+ @Test
+ public void testAssembleRemoveFlows() throws Exception {
+ final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleRemoveFlows(batchBag, 0, flowsToRemove);
+
+ Assert.assertEquals(6, lastOrder);
+ Assert.assertEquals(2, batchBag.size());
+ Assert.assertEquals(FlatBatchRemoveFlowCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchRemoveFlowCase) batchBag.get(0).getBatchChoice())
+ .getFlatBatchRemoveFlow().size());
+ Assert.assertEquals(FlatBatchRemoveFlowCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchRemoveFlowCase) batchBag.get(1).getBatchChoice())
+ .getFlatBatchRemoveFlow().size());
+ }
+
+ @Test
+ public void testAssembleAddOrUpdateGroups() throws Exception {
+ final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleAddOrUpdateGroups(batchBag, 0, groupsToAddOrUpdate);
+
+ Assert.assertEquals(9, lastOrder);
+ Assert.assertEquals(3, batchBag.size());
+ Assert.assertEquals(FlatBatchAddGroupCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchAddGroupCase) batchBag.get(0).getBatchChoice())
+ .getFlatBatchAddGroup().size());
+ Assert.assertEquals(FlatBatchAddGroupCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchAddGroupCase) batchBag.get(1).getBatchChoice())
+ .getFlatBatchAddGroup().size());
+ Assert.assertEquals(FlatBatchUpdateGroupCase.class, batchBag.get(2).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchUpdateGroupCase) batchBag.get(2).getBatchChoice())
+ .getFlatBatchUpdateGroup().size());
+ }
+
+ @Test
+ public void testAssembleRemoveGroups() throws Exception {
+ final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleRemoveGroups(batchBag, 0, groupsToRemove);
+
+ Assert.assertEquals(6, lastOrder);
+ Assert.assertEquals(2, batchBag.size());
+ Assert.assertEquals(FlatBatchRemoveGroupCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchRemoveGroupCase) batchBag.get(0).getBatchChoice())
+ .getFlatBatchRemoveGroup().size());
+ Assert.assertEquals(FlatBatchRemoveGroupCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchRemoveGroupCase) batchBag.get(1).getBatchChoice())
+ .getFlatBatchRemoveGroup().size());
+ }
+
+ @Test
+ public void testAssembleAddOrUpdateMeters() throws Exception {
+ final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleAddOrUpdateMeters(batchBag, 0, metersToAddOrUpdate);
+
+ Assert.assertEquals(6, lastOrder);
+ Assert.assertEquals(2, batchBag.size());
+ Assert.assertEquals(FlatBatchAddMeterCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchAddMeterCase) batchBag.get(0).getBatchChoice())
+ .getFlatBatchAddMeter().size());
+ Assert.assertEquals(FlatBatchUpdateMeterCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchUpdateMeterCase) batchBag.get(1).getBatchChoice())
+ .getFlatBatchUpdateMeter().size());
+ }
+
+ @Test
+ public void testAssembleRemoveMeters() throws Exception {
+ final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleRemoveMeters(batchBag, 0, metersToRemove);
+
+ Assert.assertEquals(3, lastOrder);
+ Assert.assertEquals(1, batchBag.size());
+ Assert.assertEquals(FlatBatchRemoveMeterCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchRemoveMeterCase) batchBag.get(0).getBatchChoice())
+ .getFlatBatchRemoveMeter().size());
+ }
+
+ @Test
+ public void testAssembleAddOrUpdateFlows() throws Exception {
+ final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleAddOrUpdateFlows(batchBag, 0, flowsToAddOrUpdate);
+
+ Assert.assertEquals(9, lastOrder);
+ Assert.assertEquals(3, batchBag.size());
+ Assert.assertEquals(FlatBatchAddFlowCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchAddFlowCase) batchBag.get(0).getBatchChoice())
+ .getFlatBatchAddFlow().size());
+ Assert.assertEquals(FlatBatchUpdateFlowCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchUpdateFlowCase) batchBag.get(1).getBatchChoice())
+ .getFlatBatchUpdateFlow().size());
+ Assert.assertEquals(FlatBatchAddFlowCase.class, batchBag.get(2).getBatchChoice().getImplementedInterface());
+ Assert.assertEquals(3, ((FlatBatchAddFlowCase) batchBag.get(2).getBatchChoice())
+ .getFlatBatchAddFlow().size());
+ }
+
+ @Test
+ public void testDecrementCounters() throws Exception {
+ final SyncCrudCounters counters = new SyncCrudCounters();
+ counters.getFlowCrudCounts().setAdded(100);
+ counters.getFlowCrudCounts().setUpdated(100);
+ counters.getFlowCrudCounts().setRemoved(100);
+
+ counters.getGroupCrudCounts().setAdded(100);
+ counters.getGroupCrudCounts().setUpdated(100);
+ counters.getGroupCrudCounts().setRemoved(100);
+
+ counters.getMeterCrudCounts().setAdded(100);
+ counters.getMeterCrudCounts().setUpdated(100);
+ counters.getMeterCrudCounts().setRemoved(100);
+
+ SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchAddFlowCaseBuilder().build(), counters);
+ SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchUpdateFlowCaseBuilder().build(), counters);
+ SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchRemoveFlowCaseBuilder().build(), counters);
+
+ SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchAddGroupCaseBuilder().build(), counters);
+ SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchUpdateGroupCaseBuilder().build(), counters);
+ SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchRemoveGroupCaseBuilder().build(), counters);
+
+ SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchAddMeterCaseBuilder().build(), counters);
+ SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchUpdateMeterCaseBuilder().build(), counters);
+ SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchRemoveMeterCaseBuilder().build(), counters);
+
+ Assert.assertEquals(99, counters.getFlowCrudCounts().getAdded());
+ Assert.assertEquals(99, counters.getFlowCrudCounts().getUpdated());
+ Assert.assertEquals(99, counters.getFlowCrudCounts().getRemoved());
+
+ Assert.assertEquals(99, counters.getGroupCrudCounts().getAdded());
+ Assert.assertEquals(99, counters.getGroupCrudCounts().getUpdated());
+ Assert.assertEquals(99, counters.getGroupCrudCounts().getRemoved());
+
+ Assert.assertEquals(99, counters.getMeterCrudCounts().getAdded());
+ Assert.assertEquals(99, counters.getMeterCrudCounts().getUpdated());
+ Assert.assertEquals(99, counters.getMeterCrudCounts().getRemoved());
+ }
+
+ @Test
+ public void testMapBachesToRanges() throws Exception {
+ final List<Batch> inputBatchBag = Lists.newArrayList(
+ new BatchBuilder().setBatchOrder(0).build(),
+ new BatchBuilder().setBatchOrder(5).build(),
+ new BatchBuilder().setBatchOrder(9).build(),
+ new BatchBuilder().setBatchOrder(15).build()
+ );
+ final Map<Range<Integer>, Batch> rangeBatchMap = SyncPlanPushStrategyFlatBatchImpl.mapBatchesToRanges(inputBatchBag, 42);
+
+ Assert.assertEquals(4, rangeBatchMap.size());
+ int idx = 0;
+ final int[] lower = new int[]{0, 5, 9, 15};
+ final int[] upper = new int[]{4, 8, 14, 41};
+ for (Map.Entry<Range<Integer>, Batch> rangeBatchEntry : rangeBatchMap.entrySet()) {
+ Assert.assertEquals(lower[idx], rangeBatchEntry.getKey().lowerEndpoint().intValue());
+ Assert.assertEquals(upper[idx], rangeBatchEntry.getKey().upperEndpoint().intValue());
+ Assert.assertSame(inputBatchBag.get(idx), rangeBatchEntry.getValue());
+ idx++;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.impl.strategy;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Future;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.openflowplugin.applications.frsync.impl.DSInputFactory;
+import org.opendaylight.openflowplugin.applications.frsync.impl.FlowForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.impl.GroupForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.impl.MeterForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.impl.TableForwarder;
+import org.opendaylight.openflowplugin.applications.frsync.util.ItemSyncBox;
+import org.opendaylight.openflowplugin.applications.frsync.util.SyncCrudCounters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link SyncPlanPushStrategyIncrementalImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SyncPlanPushStrategyIncrementalImplTest {
+
+ private static final NodeId NODE_ID = new NodeId("unit-nodeId");
+ private static final InstanceIdentifier<FlowCapableNode> NODE_IDENT = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, new NodeKey(NODE_ID)).augmentation(FlowCapableNode.class);
+
+ private SyncPlanPushStrategyIncrementalImpl syncPlanPushStrategy;
+
+ @Mock
+ private DataBroker db;
+ @Mock
+ private GroupForwarder groupCommitter;
+ @Mock
+ private FlowForwarder flowCommitter;
+ @Mock
+ private MeterForwarder meterCommitter;
+ @Mock
+ private TableForwarder tableCommitter;
+ @Mock
+ private FlowCapableTransactionService flowCapableTxService;
+
+ @Captor
+ private ArgumentCaptor<Group> groupCaptor;
+ @Captor
+ private ArgumentCaptor<Group> groupUpdateCaptor;
+ @Captor
+ private ArgumentCaptor<Flow> flowCaptor;
+ @Captor
+ private ArgumentCaptor<Flow> flowUpdateCaptor;
+ @Captor
+ private ArgumentCaptor<Meter> meterCaptor;
+ @Captor
+ private ArgumentCaptor<Meter> meterUpdateCaptor;
+ @Captor
+ private ArgumentCaptor<TableFeatures> tableFeaturesCaptor;
+
+ private SyncCrudCounters counters;
+
+ private List<ItemSyncBox<Group>> groupsToAddOrUpdate;
+ private List<ItemSyncBox<Group>> groupsToRemove;
+ private ItemSyncBox<Meter> metersToAddOrUpdate;
+ private ItemSyncBox<Meter> metersToRemove;
+ private Map<TableKey, ItemSyncBox<Flow>> flowsToAddOrUpdate;
+ private Map<TableKey, ItemSyncBox<Flow>> flowsToRemove;
+
+ public SyncPlanPushStrategyIncrementalImplTest() {
+ groupsToAddOrUpdate = Lists.newArrayList(DiffInputFactory.createGroupSyncBox(1, 2, 3),
+ DiffInputFactory.createGroupSyncBoxWithUpdates(4, 5, 6));
+ groupsToRemove = Lists.newArrayList(DiffInputFactory.createGroupSyncBox(1, 2, 3),
+ DiffInputFactory.createGroupSyncBox(4, 5, 6));
+
+ metersToAddOrUpdate = DiffInputFactory.createMeterSyncBoxWithUpdates(1, 2, 3);
+ metersToRemove = DiffInputFactory.createMeterSyncBox(1, 2, 3);
+
+ flowsToAddOrUpdate = new HashMap<>();
+ flowsToAddOrUpdate.put(new TableKey((short) 0), DiffInputFactory.createFlowSyncBox("1", "2", "3"));
+ flowsToAddOrUpdate.put(new TableKey((short) 1), DiffInputFactory.createFlowSyncBoxWithUpdates("4", "5", "6"));
+ flowsToRemove = new HashMap<>();
+ flowsToRemove.put(new TableKey((short) 0), DiffInputFactory.createFlowSyncBox("1", "2", "3"));
+ flowsToRemove.put(new TableKey((short) 1), DiffInputFactory.createFlowSyncBox("4", "5", "6"));
+ }
+
+ @Test
+ public void testExecuteSyncStrategy() throws Exception {
+ final SynchronizationDiffInput diffInput = new SynchronizationDiffInput(NODE_IDENT,
+ groupsToAddOrUpdate, metersToAddOrUpdate, flowsToAddOrUpdate, flowsToRemove, metersToRemove, groupsToRemove);
+
+ final SyncCrudCounters counters = new SyncCrudCounters();
+ final ListenableFuture<RpcResult<Void>> rpcResult = syncPlanPushStrategy.executeSyncStrategy(
+ RpcResultBuilder.<Void>success().buildFuture(), diffInput, counters);
+
+ Mockito.verify(groupCommitter, Mockito.times(6)).add(Matchers.<InstanceIdentifier<Group>>any(),Matchers.<Group>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.verify(groupCommitter, Mockito.times(3)).update(Matchers.<InstanceIdentifier<Group>>any(),Matchers.<Group>any(),
+ Matchers.<Group>any(), Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.verify(groupCommitter, Mockito.times(6)).remove(Matchers.<InstanceIdentifier<Group>>any(),Matchers.<Group>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.verify(flowCommitter, Mockito.times(6)).add(Matchers.<InstanceIdentifier<Flow>>any(),Matchers.<Flow>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.verify(flowCommitter, Mockito.times(3)).update(Matchers.<InstanceIdentifier<Flow>>any(),Matchers.<Flow>any(),
+ Matchers.<Flow>any(), Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.verify(flowCommitter, Mockito.times(6)).remove(Matchers.<InstanceIdentifier<Flow>>any(),Matchers.<Flow>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.verify(meterCommitter, Mockito.times(3)).add(Matchers.<InstanceIdentifier<Meter>>any(), Matchers.<Meter>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.verify(meterCommitter, Mockito.times(3)).update(Matchers.<InstanceIdentifier<Meter>>any(), Matchers.<Meter>any(),
+ Matchers.<Meter>any(), Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.verify(meterCommitter, Mockito.times(3)).remove(Matchers.<InstanceIdentifier<Meter>>any(), Matchers.<Meter>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+
+ Assert.assertTrue(rpcResult.isDone());
+ Assert.assertTrue(rpcResult.get().isSuccessful());
+
+ Assert.assertEquals(6, counters.getFlowCrudCounts().getAdded());
+ Assert.assertEquals(3, counters.getFlowCrudCounts().getUpdated());
+ Assert.assertEquals(6, counters.getFlowCrudCounts().getRemoved());
+
+ Assert.assertEquals(6, counters.getGroupCrudCounts().getAdded());
+ Assert.assertEquals(3, counters.getGroupCrudCounts().getUpdated());
+ Assert.assertEquals(6, counters.getGroupCrudCounts().getRemoved());
+
+ Assert.assertEquals(3, counters.getMeterCrudCounts().getAdded());
+ Assert.assertEquals(3, counters.getMeterCrudCounts().getUpdated());
+ Assert.assertEquals(3, counters.getMeterCrudCounts().getRemoved());
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ Mockito.when(flowCapableTxService.sendBarrier(Matchers.<SendBarrierInput>any()))
+ .thenReturn(RpcResultBuilder.success((Void) null).buildFuture());
+
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(groupCommitter).add(
+ Matchers.<InstanceIdentifier<Group>>any(), Matchers.<Group>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(groupCommitter).update(
+ Matchers.<InstanceIdentifier<Group>>any(), Matchers.<Group>any(), Matchers.<Group>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(groupCommitter).remove(
+ Matchers.<InstanceIdentifier<Group>>any(), Matchers.<Group>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(flowCommitter).add(
+ Matchers.<InstanceIdentifier<Flow>>any(), Matchers.<Flow>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(flowCommitter).update(
+ Matchers.<InstanceIdentifier<Flow>>any(), Matchers.<Flow>any(), Matchers.<Flow>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(flowCommitter).remove(
+ Matchers.<InstanceIdentifier<Flow>>any(), Matchers.<Flow>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(meterCommitter).add(
+ Matchers.<InstanceIdentifier<Meter>>any(), Matchers.<Meter>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(meterCommitter).update(
+ Matchers.<InstanceIdentifier<Meter>>any(), Matchers.<Meter>any(), Matchers.<Meter>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(meterCommitter).remove(
+ Matchers.<InstanceIdentifier<Meter>>any(), Matchers.<Meter>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+
+ Mockito.doAnswer(createSalServiceFutureAnswer()).when(tableCommitter).update(
+ Matchers.<InstanceIdentifier<TableFeatures>>any(), Matchers.<TableFeatures>any(), Matchers.<TableFeatures>any(),
+ Matchers.<InstanceIdentifier<FlowCapableNode>>any());
+
+ syncPlanPushStrategy = new SyncPlanPushStrategyIncrementalImpl()
+ .setMeterForwarder(meterCommitter)
+ .setTableForwarder(tableCommitter)
+ .setGroupForwarder(groupCommitter)
+ .setFlowForwarder(flowCommitter)
+ .setTransactionService(flowCapableTxService);
+
+ counters = new SyncCrudCounters();
+ }
+
+ private <O> Answer<Future<RpcResult<O>>> createSalServiceFutureAnswer() {
+ return new Answer<Future<RpcResult<O>>>() {
+ @Override
+ public Future<RpcResult<O>> answer(final InvocationOnMock invocation) throws Throwable {
+ return RpcResultBuilder.<O>success().buildFuture();
+ }
+ };
+ }
+
+ @Test
+ public void testAddMissingFlows() throws Exception {
+ Mockito.when(flowCommitter.add(Matchers.<InstanceIdentifier<Flow>>any(), flowCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new AddFlowOutputBuilder().build()).buildFuture());
+
+ final ItemSyncBox<Flow> flowBox = new ItemSyncBox<>();
+ flowBox.getItemsToPush().add(DSInputFactory.createFlow("f3", 3));
+ flowBox.getItemsToPush().add(DSInputFactory.createFlow("f4", 4));
+
+ final Map<TableKey, ItemSyncBox<Flow>> flowBoxMap = new LinkedHashMap<>();
+ flowBoxMap.put(new TableKey((short) 0), flowBox);
+
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.addMissingFlows(
+ NODE_ID, NODE_IDENT, flowBoxMap, counters);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<Flow> flowCaptorAllValues = flowCaptor.getAllValues();
+ Assert.assertEquals(2, flowCaptorAllValues.size());
+ Assert.assertEquals("f3", flowCaptorAllValues.get(0).getId().getValue());
+ Assert.assertEquals("f4", flowCaptorAllValues.get(1).getId().getValue());
+
+ final InOrder inOrderFlow = Mockito.inOrder(flowCapableTxService, flowCommitter);
+ inOrderFlow.verify(flowCommitter, Mockito.times(2)).add(Matchers.<InstanceIdentifier<Flow>>any(),
+ Matchers.<Flow>any(), Matchers.eq(NODE_IDENT));
+ //TODO: uncomment when enabled in impl
+// inOrderFlow.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ inOrderFlow.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testRemoveRedundantFlows() throws Exception {
+ Mockito.when(flowCommitter.remove(Matchers.<InstanceIdentifier<Flow>>any(), flowCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new RemoveFlowOutputBuilder().build()).buildFuture());
+
+ final ItemSyncBox<Flow> flowBox = new ItemSyncBox<>();
+ flowBox.getItemsToPush().add(DSInputFactory.createFlow("f3", 3));
+ flowBox.getItemsToPush().add(DSInputFactory.createFlow("f4", 4));
+
+ final Map<TableKey, ItemSyncBox<Flow>> flowBoxMap = new LinkedHashMap<>();
+ flowBoxMap.put(new TableKey((short) 0), flowBox);
+
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.removeRedundantFlows(
+ NODE_ID, NODE_IDENT, flowBoxMap, counters);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<Flow> flowCaptorAllValues = flowCaptor.getAllValues();
+ Assert.assertEquals(2, flowCaptorAllValues.size());
+ Assert.assertEquals("f3", flowCaptorAllValues.get(0).getId().getValue());
+ Assert.assertEquals("f4", flowCaptorAllValues.get(1).getId().getValue());
+
+ final InOrder inOrderFlow = Mockito.inOrder(flowCapableTxService, flowCommitter);
+ inOrderFlow.verify(flowCommitter, Mockito.times(2)).remove(Matchers.<InstanceIdentifier<Flow>>any(),
+ Matchers.<Flow>any(), Matchers.eq(NODE_IDENT));
+ inOrderFlow.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ inOrderFlow.verifyNoMoreInteractions();
+ }
+
+
+ @Test
+ public void testAddMissingFlows_withUpdate() throws Exception {
+ Mockito.when(flowCommitter.add(Matchers.<InstanceIdentifier<Flow>>any(), flowCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new AddFlowOutputBuilder().build()).buildFuture());
+
+ Mockito.when(flowCommitter.update(Matchers.<InstanceIdentifier<Flow>>any(),
+ flowUpdateCaptor.capture(), flowUpdateCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new UpdateFlowOutputBuilder().build()).buildFuture());
+
+ final ItemSyncBox<Flow> flowBox = new ItemSyncBox<>();
+ flowBox.getItemsToPush().add(DSInputFactory.createFlow("f3", 3));
+ flowBox.getItemsToPush().add(DSInputFactory.createFlow("f4", 4));
+ flowBox.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(
+ DSInputFactory.createFlow("f1", 1), DSInputFactory.createFlowWithInstruction("f1", 1)));
+
+ final Map<TableKey, ItemSyncBox<Flow>> flowBoxMap = new LinkedHashMap<>();
+ flowBoxMap.put(new TableKey((short) 0), flowBox);
+
+
+ //TODO: replace null
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.addMissingFlows(
+ NODE_ID, NODE_IDENT, flowBoxMap, counters);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<Flow> flowCaptorAllValues = flowCaptor.getAllValues();
+ Assert.assertEquals(2, flowCaptorAllValues.size());
+ Assert.assertEquals("f3", flowCaptorAllValues.get(0).getId().getValue());
+ Assert.assertEquals("f4", flowCaptorAllValues.get(1).getId().getValue());
+
+ final List<Flow> flowUpdateCaptorAllValues = flowUpdateCaptor.getAllValues();
+ Assert.assertEquals(2, flowUpdateCaptorAllValues.size());
+ Assert.assertEquals("f1", flowUpdateCaptorAllValues.get(0).getId().getValue());
+ Assert.assertEquals("f1", flowUpdateCaptorAllValues.get(1).getId().getValue());
+
+ final InOrder inOrderFlow = Mockito.inOrder(flowCapableTxService, flowCommitter);
+ // add f3, f4
+ inOrderFlow.verify(flowCommitter, Mockito.times(2)).add(Matchers.<InstanceIdentifier<Flow>>any(),
+ Matchers.<Flow>any(), Matchers.eq(NODE_IDENT));
+ // update f1
+ inOrderFlow.verify(flowCommitter).update(Matchers.<InstanceIdentifier<Flow>>any(),
+ Matchers.<Flow>any(), Matchers.<Flow>any(), Matchers.eq(NODE_IDENT));
+ //TODO: uncomment when enabled in impl
+// inOrderFlow.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+
+ inOrderFlow.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testAddMissingMeters() throws Exception {
+ Mockito.when(meterCommitter.add(Matchers.<InstanceIdentifier<Meter>>any(), meterCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new AddMeterOutputBuilder().build()).buildFuture());
+
+ final ItemSyncBox<Meter> meterSyncBox = new ItemSyncBox<>();
+ meterSyncBox.getItemsToPush().add(DSInputFactory.createMeter(2L));
+ meterSyncBox.getItemsToPush().add(DSInputFactory.createMeter(4L));
+
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.addMissingMeters(
+ NODE_ID, NODE_IDENT, meterSyncBox, counters);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<Meter> metercaptorAllValues = meterCaptor.getAllValues();
+ Assert.assertEquals(2, metercaptorAllValues.size());
+ Assert.assertEquals(2L, metercaptorAllValues.get(0).getMeterId().getValue().longValue());
+ Assert.assertEquals(4L, metercaptorAllValues.get(1).getMeterId().getValue().longValue());
+
+ final InOrder inOrderMeter = Mockito.inOrder(flowCapableTxService, meterCommitter);
+ inOrderMeter.verify(meterCommitter, Mockito.times(2)).add(Matchers.<InstanceIdentifier<Meter>>any(),
+ Matchers.<Meter>any(), Matchers.eq(NODE_IDENT));
+ //TODO: uncomment when enabled in impl
+// inOrderMeter.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ inOrderMeter.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testAddMissingMeters_withUpdate() throws Exception {
+ Mockito.when(meterCommitter.add(Matchers.<InstanceIdentifier<Meter>>any(), meterCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new AddMeterOutputBuilder().build()).buildFuture());
+
+ Mockito.when(meterCommitter.update(Matchers.<InstanceIdentifier<Meter>>any(),
+ meterUpdateCaptor.capture(), meterUpdateCaptor.capture(), Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new UpdateMeterOutputBuilder().build()).buildFuture());
+
+ final ItemSyncBox<Meter> meterSyncBox = new ItemSyncBox<>();
+ meterSyncBox.getItemsToPush().add(DSInputFactory.createMeter(2L));
+ meterSyncBox.getItemsToPush().add(DSInputFactory.createMeter(4L));
+ meterSyncBox.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(
+ DSInputFactory.createMeter(1L), DSInputFactory.createMeterWithBody(1L)));
+
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.addMissingMeters(
+ NODE_ID, NODE_IDENT, meterSyncBox, counters);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<Meter> meterCaptorAllValues = meterCaptor.getAllValues();
+ Assert.assertEquals(2, meterCaptorAllValues.size());
+ Assert.assertEquals(2L, meterCaptorAllValues.get(0).getMeterId().getValue().longValue());
+ Assert.assertEquals(4L, meterCaptorAllValues.get(1).getMeterId().getValue().longValue());
+
+
+ final List<Meter> meterUpdateCaptorAllValues = meterUpdateCaptor.getAllValues();
+ Assert.assertEquals(2, meterUpdateCaptorAllValues.size());
+ Assert.assertEquals(1L, meterUpdateCaptorAllValues.get(0).getMeterId().getValue().longValue());
+ Assert.assertEquals(1L, meterUpdateCaptorAllValues.get(1).getMeterId().getValue().longValue());
+
+ final InOrder inOrderMeters = Mockito.inOrder(flowCapableTxService, meterCommitter);
+ inOrderMeters.verify(meterCommitter, Mockito.times(2)).add(Matchers.<InstanceIdentifier<Meter>>any(),
+ Matchers.<Meter>any(), Matchers.eq(NODE_IDENT));
+ inOrderMeters.verify(meterCommitter).update(Matchers.<InstanceIdentifier<Meter>>any(),
+ Matchers.<Meter>any(), Matchers.<Meter>any(), Matchers.eq(NODE_IDENT));
+ //TODO: uncomment when enabled in impl
+// inOrderMeters.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+
+ inOrderMeters.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testRemoveRedundantMeters() throws Exception {
+ Mockito.when(meterCommitter.remove(Matchers.<InstanceIdentifier<Meter>>any(), meterCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new RemoveMeterOutputBuilder().build()).buildFuture());
+
+ final ItemSyncBox<Meter> meterSyncBox = new ItemSyncBox<>();
+ meterSyncBox.getItemsToPush().add(DSInputFactory.createMeter(2L));
+ meterSyncBox.getItemsToPush().add(DSInputFactory.createMeter(4L));
+ meterSyncBox.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(
+ DSInputFactory.createMeter(1L), DSInputFactory.createMeterWithBody(1L)));
+
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.removeRedundantMeters(
+ NODE_ID, NODE_IDENT, meterSyncBox, counters);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<Meter> metercaptorAllValues = meterCaptor.getAllValues();
+ Assert.assertEquals(2, metercaptorAllValues.size());
+ Assert.assertEquals(2L, metercaptorAllValues.get(0).getMeterId().getValue().longValue());
+ Assert.assertEquals(4L, metercaptorAllValues.get(1).getMeterId().getValue().longValue());
+
+ final InOrder inOrderMeter = Mockito.inOrder(flowCapableTxService, meterCommitter);
+ inOrderMeter.verify(meterCommitter, Mockito.times(2)).remove(Matchers.<InstanceIdentifier<Meter>>any(),
+ Matchers.<Meter>any(), Matchers.eq(NODE_IDENT));
+ //TODO: uncomment when enabled in impl
+// inOrderMeter.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ inOrderMeter.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testAddMissingGroups() throws Exception {
+ Mockito.when(groupCommitter.add(Matchers.<InstanceIdentifier<Group>>any(), groupCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new AddGroupOutputBuilder().build()).buildFuture());
+
+ ItemSyncBox<Group> groupBox1 = new ItemSyncBox<>();
+ groupBox1.getItemsToPush().add(DSInputFactory.createGroup(2L));
+
+ ItemSyncBox<Group> groupBox2 = new ItemSyncBox<>();
+ groupBox2.getItemsToPush().add(DSInputFactory.createGroupWithPreconditions(3L, 2L));
+ groupBox2.getItemsToPush().add(DSInputFactory.createGroupWithPreconditions(4L, 2L));
+
+ ItemSyncBox<Group> groupBox3 = new ItemSyncBox<>();
+ groupBox3.getItemsToPush().add(DSInputFactory.createGroupWithPreconditions(5L, 3L, 4L));
+
+ final List<ItemSyncBox<Group>> groupBoxLot = Lists.newArrayList(groupBox1, groupBox2, groupBox3);
+
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.addMissingGroups(
+ NODE_ID, NODE_IDENT, groupBoxLot, counters);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<Group> groupCaptorAllValues = groupCaptor.getAllValues();
+ Assert.assertEquals(4, groupCaptorAllValues.size());
+ Assert.assertEquals(2L, groupCaptorAllValues.get(0).getGroupId().getValue().longValue());
+ Assert.assertEquals(3L, groupCaptorAllValues.get(1).getGroupId().getValue().longValue());
+ Assert.assertEquals(4L, groupCaptorAllValues.get(2).getGroupId().getValue().longValue());
+ Assert.assertEquals(5L, groupCaptorAllValues.get(3).getGroupId().getValue().longValue());
+
+ final InOrder inOrderGroups = Mockito.inOrder(flowCapableTxService, groupCommitter);
+ // add 2
+ inOrderGroups.verify(groupCommitter).add(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroups.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ // add 3, 4
+ inOrderGroups.verify(groupCommitter, Mockito.times(2)).add(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroups.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ // add 5
+ inOrderGroups.verify(groupCommitter).add(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroups.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+
+ inOrderGroups.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testAddMissingGroups_withUpdate() throws Exception {
+ Mockito.when(groupCommitter.add(Matchers.<InstanceIdentifier<Group>>any(), groupCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new AddGroupOutputBuilder().build()).buildFuture());
+
+ Mockito.when(groupCommitter.update(Matchers.<InstanceIdentifier<Group>>any(),
+ groupUpdateCaptor.capture(), groupUpdateCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new UpdateGroupOutputBuilder().build()).buildFuture());
+
+ ItemSyncBox<Group> groupBox1 = new ItemSyncBox<>();
+ groupBox1.getItemsToPush().add(DSInputFactory.createGroup(2L));
+ groupBox1.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(
+ DSInputFactory.createGroup(1L), DSInputFactory.createGroupWithAction(1L)));
+
+ ItemSyncBox<Group> groupBox2 = new ItemSyncBox<>();
+ groupBox2.getItemsToPush().add(DSInputFactory.createGroupWithPreconditions(3L, 2L));
+ groupBox2.getItemsToPush().add(DSInputFactory.createGroupWithPreconditions(4L, 2L));
+
+ ItemSyncBox<Group> groupBox3 = new ItemSyncBox<>();
+ groupBox3.getItemsToPush().add(DSInputFactory.createGroupWithPreconditions(5L, 3L, 4L));
+
+ final List<ItemSyncBox<Group>> groupBoxLot = Lists.newArrayList(groupBox1, groupBox2, groupBox3);
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.addMissingGroups(
+ NODE_ID, NODE_IDENT, groupBoxLot, counters);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<Group> groupCaptorAllValues = groupCaptor.getAllValues();
+ Assert.assertEquals(4, groupCaptorAllValues.size());
+ Assert.assertEquals(2L, groupCaptorAllValues.get(0).getGroupId().getValue().longValue());
+ Assert.assertEquals(3L, groupCaptorAllValues.get(1).getGroupId().getValue().longValue());
+ Assert.assertEquals(4L, groupCaptorAllValues.get(2).getGroupId().getValue().longValue());
+ Assert.assertEquals(5L, groupCaptorAllValues.get(3).getGroupId().getValue().longValue());
+
+ final List<Group> groupUpdateCaptorAllValues = groupUpdateCaptor.getAllValues();
+ Assert.assertEquals(2, groupUpdateCaptorAllValues.size());
+ Assert.assertEquals(1L, groupUpdateCaptorAllValues.get(0).getGroupId().getValue().longValue());
+ Assert.assertEquals(1L, groupUpdateCaptorAllValues.get(1).getGroupId().getValue().longValue());
+
+ final InOrder inOrderGroups = Mockito.inOrder(flowCapableTxService, groupCommitter);
+
+ // add 2, update 1
+ inOrderGroups.verify(groupCommitter).add(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroups.verify(groupCommitter).update(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroups.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+
+ // add 3, 4
+ inOrderGroups.verify(groupCommitter, Mockito.times(2)).add(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroups.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ // add 5
+ inOrderGroups.verify(groupCommitter).add(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroups.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+
+ inOrderGroups.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testRemoveRedundantGroups() throws Exception {
+ Mockito.when(groupCommitter.remove(Matchers.<InstanceIdentifier<Group>>any(), groupCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new RemoveGroupOutputBuilder().build()).buildFuture());
+
+ ItemSyncBox<Group> groupBox1 = new ItemSyncBox<>();
+ groupBox1.getItemsToPush().add(DSInputFactory.createGroup(2L));
+ groupBox1.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(
+ DSInputFactory.createGroup(1L), DSInputFactory.createGroupWithAction(1L)));
+
+ ItemSyncBox<Group> groupBox2 = new ItemSyncBox<>();
+ groupBox2.getItemsToPush().add(DSInputFactory.createGroupWithPreconditions(3L, 2L));
+ groupBox2.getItemsToPush().add(DSInputFactory.createGroupWithPreconditions(4L, 2L));
+
+ ItemSyncBox<Group> groupBox3 = new ItemSyncBox<>();
+ groupBox3.getItemsToPush().add(DSInputFactory.createGroupWithPreconditions(5L, 3L, 4L));
+
+ final List<ItemSyncBox<Group>> groupBoxLot = Lists.newArrayList(groupBox1, groupBox2, groupBox3);
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.removeRedundantGroups(
+ NODE_ID, NODE_IDENT, groupBoxLot, counters);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<Group> groupCaptorAllValues = groupCaptor.getAllValues();
+ Assert.assertEquals(4, groupCaptorAllValues.size());
+ Assert.assertEquals(5L, groupCaptorAllValues.get(0).getGroupId().getValue().longValue());
+ Assert.assertEquals(3L, groupCaptorAllValues.get(1).getGroupId().getValue().longValue());
+ Assert.assertEquals(4L, groupCaptorAllValues.get(2).getGroupId().getValue().longValue());
+ Assert.assertEquals(2L, groupCaptorAllValues.get(3).getGroupId().getValue().longValue());
+
+ final InOrder inOrderGroup = Mockito.inOrder(flowCapableTxService, groupCommitter);
+ // remove 5
+ inOrderGroup.verify(groupCommitter).remove(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroup.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ // remove 3, 4
+ inOrderGroup.verify(groupCommitter, Mockito.times(2)).remove(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroup.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ // remove 2
+ inOrderGroup.verify(groupCommitter).remove(Matchers.<InstanceIdentifier<Group>>any(),
+ Matchers.<Group>any(), Matchers.eq(NODE_IDENT));
+ inOrderGroup.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+
+ inOrderGroup.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testUpdateTableFeatures() throws Exception {
+ Mockito.when(tableCommitter.update(Matchers.<InstanceIdentifier<TableFeatures>>any(),
+ Matchers.isNull(TableFeatures.class), tableFeaturesCaptor.capture(),
+ Matchers.same(NODE_IDENT)))
+ .thenReturn(RpcResultBuilder.success(new UpdateTableOutputBuilder().build()).buildFuture());
+
+ final FlowCapableNode operational = new FlowCapableNodeBuilder()
+ .setTable(Collections.singletonList(new TableBuilder()
+ .setId((short) 1)
+ .build()))
+ .setTableFeatures(Collections.singletonList(new TableFeaturesBuilder()
+ .setName("test table features")
+ .setTableId((short) 1)
+ .build()))
+ .build();
+
+ final ListenableFuture<RpcResult<Void>> result = syncPlanPushStrategy.updateTableFeatures(
+ NODE_IDENT, operational);
+
+ Assert.assertTrue(result.isDone());
+ Assert.assertTrue(result.get().isSuccessful());
+
+ final List<TableFeatures> groupCaptorAllValues = tableFeaturesCaptor.getAllValues();
+ //TODO: uncomment when enabled in impl
+// Assert.assertEquals(1, groupCaptorAllValues.size());
+// Assert.assertEquals("test table features", groupCaptorAllValues.get(0).getName());
+// Assert.assertEquals(1, groupCaptorAllValues.get(0).getTableId().intValue());
+
+ Mockito.verify(flowCapableTxService).sendBarrier(Matchers.<SendBarrierInput>any());
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import com.google.common.base.Splitter;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link ReconcileUtil}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ReconcileUtilTest {
+
+ private static final NodeId NODE_ID = new NodeId("unit-node-id");
+ private final InstanceIdentifier<Node> NODE_IDENT = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, new NodeKey(NODE_ID));
+ private static final Splitter COMMA_SPLITTER = Splitter.on(",");
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+ @Mock
+ private FlowCapableTransactionService flowCapableService;
+ @Captor
+ private ArgumentCaptor<SendBarrierInput> barrierInputCaptor;
+
+ @Test
+ public void testChainBarrierFlush() throws Exception {
+ SettableFuture<RpcResult<Void>> testRabbit = SettableFuture.create();
+ final ListenableFuture<RpcResult<Void>> vehicle =
+ Futures.transform(testRabbit, ReconcileUtil.chainBarrierFlush(NODE_IDENT, flowCapableService));
+ Mockito.when(flowCapableService.sendBarrier(barrierInputCaptor.capture()))
+ .thenReturn(RpcResultBuilder.<Void>success().buildFuture());
+
+ Mockito.verify(flowCapableService, Mockito.never()).sendBarrier(Matchers.<SendBarrierInput>any());
+ Assert.assertFalse(vehicle.isDone());
+
+ testRabbit.set(RpcResultBuilder.<Void>success().build());
+ Mockito.verify(flowCapableService).sendBarrier(Matchers.<SendBarrierInput>any());
+ Assert.assertTrue(vehicle.isDone());
+ Assert.assertTrue(vehicle.get().isSuccessful());
+ }
+
+ @Test
+ public void testCreateRpcResultCondenser() throws Exception {
+
+ }
+
+ /**
+ * add one missing group
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testResolveAndDivideGroupDiffs1() throws Exception {
+ final Map<Long, Group> installedGroups = new HashMap<>();
+ installedGroups.put(1L, createGroup(1L));
+ installedGroups.put(2L, createGroup(2L));
+ installedGroups.put(3L, createGroup(3L));
+
+ final List<Group> pendingGroups = new ArrayList<>();
+ pendingGroups.add(createGroup(2L));
+ pendingGroups.add(createGroup(3L));
+ pendingGroups.add(createGroup(4L));
+
+ final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
+ NODE_ID, installedGroups, pendingGroups);
+
+ Assert.assertEquals(1, plan.size());
+
+ Assert.assertEquals(1, plan.get(0).getItemsToPush().size());
+ Assert.assertEquals(4L, plan.get(0).getItemsToPush().iterator().next().getKey().getGroupId().getValue().longValue());
+ Assert.assertEquals(0, plan.get(0).getItemsToUpdate().size());
+ }
+
+ /**
+ * add 3 groups with dependencies - 3 steps involved
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testResolveAndDivideGroupDiffs2() throws Exception {
+ final Map<Long, Group> installedGroups = new HashMap<>();
+ installedGroups.put(1L, createGroup(1L));
+
+ final List<Group> pendingGroups = new ArrayList<>();
+ pendingGroups.add(createGroup(2L));
+ pendingGroups.add(createGroupWithPreconditions(3L, 2L, 4L));
+ pendingGroups.add(createGroupWithPreconditions(4L, 2L));
+
+ final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
+ NODE_ID, installedGroups, pendingGroups);
+
+ Assert.assertEquals(3, plan.size());
+
+ Assert.assertEquals(1, plan.get(0).getItemsToPush().size());
+ Assert.assertEquals(2L, plan.get(0).getItemsToPush().iterator().next().getKey().getGroupId().getValue().longValue());
+ Assert.assertEquals(0, plan.get(0).getItemsToUpdate().size());
+
+ Assert.assertEquals(1, plan.get(1).getItemsToPush().size());
+ Assert.assertEquals(4L, plan.get(1).getItemsToPush().iterator().next().getKey().getGroupId().getValue().longValue());
+ Assert.assertEquals(0, plan.get(1).getItemsToUpdate().size());
+
+ Assert.assertEquals(1, plan.get(2).getItemsToPush().size());
+ Assert.assertEquals(3L, plan.get(2).getItemsToPush().iterator().next().getKey().getGroupId().getValue().longValue());
+ Assert.assertEquals(0, plan.get(2).getItemsToUpdate().size());
+ }
+
+ /**
+ * no actions taken - installed and pending groups are the same
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testResolveAndDivideGroupDiffs3() throws Exception {
+ final Map<Long, Group> installedGroups = new HashMap<>();
+ installedGroups.put(1L, createGroup(1L));
+ installedGroups.put(2L, createGroupWithPreconditions(2L, 1L));
+
+ final List<Group> pendingGroups = new ArrayList<>();
+ pendingGroups.add(createGroup(1L));
+ pendingGroups.add(createGroupWithPreconditions(2L, 1L));
+
+ final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
+ NODE_ID, installedGroups, pendingGroups);
+
+ Assert.assertEquals(0, plan.size());
+ }
+
+ /**
+ * update 1 group
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testResolveAndDivideGroupDiffs4() throws Exception {
+ final Map<Long, Group> installedGroups = new HashMap<>();
+ installedGroups.put(1L, createGroup(1L));
+ installedGroups.put(2L, createGroup(2L));
+
+ final List<Group> pendingGroups = new ArrayList<>();
+ pendingGroups.add(createGroupWithPreconditions(1L, 2L));
+ pendingGroups.add(createGroup(2L));
+
+ final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
+ NODE_ID, installedGroups, pendingGroups);
+
+ Assert.assertEquals(1, plan.size());
+ Assert.assertEquals(0, plan.get(0).getItemsToPush().size());
+ Assert.assertEquals(1, plan.get(0).getItemsToUpdate().size());
+ final ItemSyncBox.ItemUpdateTuple<Group> firstItemUpdateTuple = plan.get(0).getItemsToUpdate().iterator().next();
+ Assert.assertEquals(1L, firstItemUpdateTuple.getOriginal().getGroupId().getValue().longValue());
+ Assert.assertEquals(1L, firstItemUpdateTuple.getUpdated().getGroupId().getValue().longValue());
+ }
+
+ /**
+ * no action taken - update 1 group will be ignored
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testResolveAndDivideGroupDiffs5() throws Exception {
+ final Map<Long, Group> installedGroups = new HashMap<>();
+ installedGroups.put(1L, createGroup(1L));
+ installedGroups.put(2L, createGroup(2L));
+
+ final List<Group> pendingGroups = new ArrayList<>();
+ pendingGroups.add(createGroupWithPreconditions(1L, 2L));
+ pendingGroups.add(createGroup(2L));
+
+ final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
+ NODE_ID, installedGroups, pendingGroups, false);
+
+ Assert.assertEquals(0, plan.size());
+ }
+
+ /**
+ * should add 1 group but preconditions are not met
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testResolveAndDivideGroupDiffs_negative1() throws Exception {
+ final Map<Long, Group> installedGroups = new HashMap<>();
+ installedGroups.put(1L, createGroup(1L));
+ installedGroups.put(2L, createGroup(2L));
+
+ final List<Group> pendingGroups = new ArrayList<>();
+ pendingGroups.add(createGroupWithPreconditions(3L, 4L));
+
+ thrown.expect(IllegalStateException.class);
+ final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
+ NODE_ID, installedGroups, pendingGroups);
+ }
+
+ /**
+ * should update 1 group but preconditions are not met
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testResolveAndDivideGroupDiffs_negative2() throws Exception {
+ final Map<Long, Group> installedGroups = new HashMap<>();
+ installedGroups.put(1L, createGroup(1L));
+ installedGroups.put(2L, createGroup(2L));
+
+ final List<Group> pendingGroups = new ArrayList<>();
+ pendingGroups.add(createGroupWithPreconditions(1L, 3L));
+
+ thrown.expect(IllegalStateException.class);
+ final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
+ NODE_ID, installedGroups, pendingGroups);
+ }
+
+ @Test
+ public void testCheckGroupPrecondition() throws Exception {
+ final Set<Long> installedGroups = new HashSet<>(Arrays.asList(new Long[]{1L, 2L}));
+
+ final Group pendingGroup1 = createGroupWithPreconditions(3L, 2L, 4L);
+ Assert.assertFalse(ReconcileUtil.checkGroupPrecondition(installedGroups, pendingGroup1));
+
+ final Group pendingGroup2 = createGroupWithPreconditions(1L, 2L);
+ Assert.assertTrue(ReconcileUtil.checkGroupPrecondition(installedGroups, pendingGroup2));
+
+ final Group pendingGroup3 = createGroupWithPreconditions(1L);
+ Assert.assertTrue(ReconcileUtil.checkGroupPrecondition(installedGroups, pendingGroup3));
+ }
+
+ private Group createGroupWithPreconditions(final long groupIdValue, final long... requiredId) {
+ final List<Action> actionBag = new ArrayList<>();
+ for (long groupIdPrecondition : requiredId) {
+ final GroupAction groupAction = new GroupActionBuilder()
+ .setGroupId(groupIdPrecondition)
+ .build();
+ final GroupActionCase groupActionCase = new GroupActionCaseBuilder()
+ .setGroupAction(groupAction)
+ .build();
+ final Action action = new ActionBuilder()
+ .setAction(groupActionCase)
+ .build();
+ actionBag.add(action);
+ }
+
+ final Bucket bucket = new BucketBuilder()
+ .setAction(actionBag)
+ .build();
+ final Buckets buckets = new BucketsBuilder()
+ .setBucket(Collections.singletonList(bucket))
+ .build();
+
+ return new GroupBuilder()
+ .setGroupId(new GroupId(groupIdValue))
+ .setBuckets(buckets)
+ .build();
+ }
+
+ private Group createGroup(final long groupIdValue) {
+ final Buckets buckets = new BucketsBuilder()
+ .setBucket(Collections.<Bucket>emptyList())
+ .build();
+ return new GroupBuilder()
+ .setGroupId(new GroupId(groupIdValue))
+ .setBuckets(buckets)
+ .build();
+ }
+
+ /**
+ * covers {@link ReconcileUtil#countTotalUpdated(Iterable)} too
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testCountTotalAdds() throws Exception {
+ List<ItemSyncBox<String>> syncPlan = new ArrayList<>();
+ ItemSyncBox<String> syncBox1 = createSyncBox("a,b", "x,y,z");
+ syncPlan.add(syncBox1);
+ syncPlan.add(syncBox1);
+ Assert.assertEquals(4, ReconcileUtil.countTotalPushed(syncPlan));
+ Assert.assertEquals(6, ReconcileUtil.countTotalUpdated(syncPlan));
+ }
+
+ private ItemSyncBox<String> createSyncBox(final String pushes, final String updates) {
+ ItemSyncBox<String> syncBox1 = new ItemSyncBox<>();
+ syncBox1.getItemsToPush().addAll(COMMA_SPLITTER.splitToList(pushes));
+ for (String orig : COMMA_SPLITTER.splitToList(updates)) {
+ syncBox1.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(orig, orig + "_updated"));
+ }
+ return syncBox1;
+ }
+
+ @Test
+ public void testResolveMeterDiffs() throws Exception {
+
+ }
+
+ @Test
+ public void testResolveFlowDiffsInTable() throws Exception {
+
+ }
+
+ @Test
+ public void testResolveFlowDiffsInAllTables() throws Exception {
+
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import java.util.Date;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+/**
+ * Test for {@link RetryRegistry}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class RetryRegistryTest {
+
+ private static final NodeId NODE_ID = new NodeId("testNode");
+ private RetryRegistry retryRegistry;
+
+ @Before
+ public void setUp() throws Exception {
+ retryRegistry = new RetryRegistry();
+ }
+
+ @Test
+ public void testRegister() {
+ Date timestamp = retryRegistry.register(NODE_ID);
+ Assert.assertEquals(true, retryRegistry.isRegistered(NODE_ID));
+ Assert.assertNotNull(timestamp);
+ }
+
+ @Test
+ public void testUnregisterIfRegistered() {
+ retryRegistry.register(NODE_ID);
+ Date timestamp = retryRegistry.unregisterIfRegistered(NODE_ID);
+ Assert.assertEquals(false, retryRegistry.isRegistered(NODE_ID));
+ Assert.assertNotNull(timestamp);
+ }
+
+ @Test
+ public void testUnregisterIfNotRegistered() {
+ Date timestamp = retryRegistry.unregisterIfRegistered(NODE_ID);
+ Assert.assertEquals(false, retryRegistry.isRegistered(NODE_ID));
+ Assert.assertNull(timestamp);
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowplugin.applications.frsync.util;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.openflowplugin.applications.frsync.SemaphoreKeeper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test for {@link SemaphoreKeeperGuavaImpl}.
+ */
+public class SemaphoreKeeperTest {
+ private static final Logger LOG = LoggerFactory.getLogger(SemaphoreKeeperTest.class);
+ private SemaphoreKeeperGuavaImpl<String> semaphoreKeeper;
+ private final String key = "11";
+
+ @Before
+ public void setUp() throws Exception {
+ semaphoreKeeper = new SemaphoreKeeperGuavaImpl(1, true);
+ }
+
+ @Test
+ public void testSummonGuard() throws Exception {
+ Semaphore semaphore1 = semaphoreKeeper.summonGuard(key);
+ final int g1FingerPrint = semaphore1.hashCode();
+ Semaphore semaphore2 = semaphoreKeeper.summonGuard(key);
+ final int g2FingerPrint = semaphore2.hashCode();
+
+ Assert.assertSame(semaphore1, semaphore2);
+ Assert.assertEquals(1, semaphore1.availablePermits());
+
+ semaphore1.acquire();
+ semaphore1.release();
+ Assert.assertEquals(1, semaphore1.availablePermits());
+ semaphore1 = null;
+ System.gc();
+
+ semaphore2.acquire();
+ semaphore2.release();
+ Assert.assertEquals(1, semaphore2.availablePermits());
+ semaphore2 = null;
+ Assert.assertEquals(g1FingerPrint, g2FingerPrint);
+
+ System.gc();
+ final Semaphore semaphore3 = semaphoreKeeper.summonGuard(key);
+ Assert.assertNotEquals(g1FingerPrint, semaphore3.hashCode());
+ }
+
+ @Test
+ public void testReleaseGuard() throws Exception {
+ for (int total = 1; total <= 10; total++) {
+ LOG.info("test run: {}", total);
+ final Worker task = new Worker(semaphoreKeeper, key);
+
+ final ExecutorService executorService = new ThreadPoolExecutor(5, 5,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>()) {
+ @Override
+ protected void afterExecute(final Runnable r, final Throwable t) {
+ super.afterExecute(r, t);
+ if (t != null) {
+ LOG.error("pool thread crashed", t);
+ }
+ }
+ };
+
+ final int steps = 10;
+ for (int i = 0; i < steps; i++) {
+ executorService.submit(task);
+ }
+ Thread.sleep(50L);
+ LOG.info("STARTING new serie");
+ System.gc();
+
+ for (int i = 0; i < steps; i++) {
+ executorService.submit(task);
+ }
+ Thread.sleep(100L);
+ System.gc();
+
+ executorService.shutdown();
+ final boolean terminated = executorService.awaitTermination(10, TimeUnit.SECONDS);
+ if (!terminated) {
+ LOG.warn("pool stuck, forcing termination");
+ executorService.shutdownNow();
+ Assert.fail("pool failed to finish gracefully");
+ }
+
+ final int counterSize = task.getCounterSize();
+ LOG.info("final counter = {}", counterSize);
+ Assert.assertEquals(20, counterSize);
+ }
+ }
+
+ private static class Worker implements Runnable {
+ private final SemaphoreKeeper<String> keeper;
+ private final String key;
+ private ConcurrentMap<Integer, Integer> counter = new ConcurrentHashMap<>();
+ private volatile int index = 0;
+
+ public Worker(SemaphoreKeeper<String> keeper, final String key) {
+ this.keeper = keeper;
+ this.key = key;
+ }
+
+ @Override
+ public void run() {
+ try {
+ final Semaphore guard = keeper.summonGuard(key);
+ Thread.sleep(2L);
+ guard.acquire();
+ counter.putIfAbsent(index, 0);
+ counter.put(index, counter.get(index) + 1);
+ LOG.debug("queue: {} [{}] - {}", guard.getQueueLength(), guard.hashCode(), counter.size());
+ index++;
+ guard.release();
+ } catch (Exception e) {
+ LOG.warn("acquiring failed.. ", e);
+ }
+ }
+
+ public int getCounterSize() {
+ return counter.size();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">\r
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">\r
+\r
+ <appender name="console" class="org.apache.log4j.ConsoleAppender">\r
+ <layout class="org.apache.log4j.PatternLayout">\r
+ <param name="ConversionPattern" value="%-6p %d{HH:mm:ss.SSS} [%10.10t] %30.30c %x - %m%n"/>\r
+ </layout>\r
+ </appender>\r
+\r
+ <logger name="org.opendaylight.openflowplugin.applications.frsync" additivity="false">\r
+ <level value="TRACE"/>\r
+ <appender-ref ref="console"/>\r
+ </logger>\r
+\r
+ <root>\r
+ <priority value="INFO"/>\r
+ <appender-ref ref="console"/>\r
+ </root>\r
+</log4j:configuration>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
-Copyright (c) 2014 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
--->
-<snapshot>
- <required-capabilities>
- <!--<capability>urn:opendaylight:params:xml:ns:yang:southbound:impl?module=southbound-impl&revision=2015-01-05</capability>-->
- <capability>urn:opendaylight:inventory?module=opendaylight-inventory&revision=2013-08-19</capability>
- <capability>urn:opendaylight:flow:inventory?module=flow-node-inventory&revision=2013-08-19</capability>
- <capability>urn:opendaylight:flow:types?module=opendaylight-flow-types&revision=2013-10-26</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:distributed-entity-ownership-service?module=distributed-entity-ownership-service&revision=2015-08-10</capability>
- </required-capabilities>
- <configuration>
-
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:inventory-manager:impl">prefix:inventory-manager-impl</type>
- <name>inventory-manager-default</name>
- <broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
- <name>binding-osgi-broker</name>
- </broker>
- <entity-ownership-service>
- <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
- <name>entity-ownership-service</name>
- </entity-ownership-service>
- </module>
- </modules>
- </data>
- </configuration>
-</snapshot>
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class InventoryActivator implements BindingAwareProvider, AutoCloseable {
+public class InventoryActivator implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(InventoryActivator.class);
- private FlowCapableInventoryProvider provider;
- final private EntityOwnershipService eos;
-
- public InventoryActivator(EntityOwnershipService eos) {
- this.eos = eos;
- }
+ private final FlowCapableInventoryProvider provider;
- @Override
- public void onSessionInitiated(final ProviderContext session) {
- DataBroker dataBroker = session.getSALService(DataBroker.class);
- NotificationProviderService salNotifiService =
- session.getSALService(NotificationProviderService.class);
+ public InventoryActivator(DataBroker dataBroker, NotificationProviderService notificationService,
+ EntityOwnershipService eos) {
+ provider = new FlowCapableInventoryProvider(dataBroker, notificationService, eos);
+ }
- provider = new FlowCapableInventoryProvider(dataBroker, salNotifiService, eos);
+ public void start() {
provider.start();
}
@Override
- public void close() throws Exception {
- if (provider != null) {
- try {
- provider.close();
- } catch (InterruptedException e) {
- LOG.warn("Interrupted while waiting for shutdown", e);
- }
- provider = null;
+ public void close() {
+ try {
+ provider.close();
+ } catch (InterruptedException e) {
+ LOG.warn("Interrupted while waiting for shutdown", e);
}
}
}
+++ /dev/null
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.inventory.manager.impl.rev150530;
-
-import org.opendaylight.openflowplugin.applications.inventory.manager.InventoryActivator;
-
-public class InventoryManagerImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.inventory.manager.impl.rev150530.AbstractInventoryManagerImplModule {
- public InventoryManagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public InventoryManagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.inventory.manager.impl.rev150530.InventoryManagerImplModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- InventoryActivator provider = new InventoryActivator(getEntityOwnershipServiceDependency());
- getBrokerDependency().registerProvider(provider);
- return provider;
- }
-
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: inventory-manager-impl yang module local name: inventory-manager-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Sat May 30 18:52:44 PDT 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.inventory.manager.impl.rev150530;
-public class InventoryManagerImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.inventory.manager.impl.rev150530.AbstractInventoryManagerImplModuleFactory {
-
-}
+++ /dev/null
-module inventory-manager-impl {
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:inventory-manager:impl";
- prefix "inventory-manager-impl";
-
- import config { prefix config; revision-date 2013-04-05; }
- import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
- import opendaylight-entity-ownership-service { prefix eos; }
-
- description
- "Service definition for inventory manager";
-
- revision "2015-05-30" {
- description
- "Initial revision";
- }
-
- identity inventory-manager-impl {
- base config:module-type;
- config:java-name-prefix InventoryManagerImpl;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case inventory-manager-impl {
- when "/config:modules/config:module/config:type = 'inventory-manager-impl'";
- container broker {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity md-sal-binding:binding-broker-osgi-registry;
- }
- }
- }
-
- container entity-ownership-service {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity eos:entity-ownership-service;
- }
- }
- }
- }
- }
-}
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
</plugin>
-
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-artifacts</id>
- <goals>
- <goal>attach-artifact</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <artifacts>
- <artifact>
- <file>${project.build.directory}/classes/initial/71-lldp-speaker.xml</file>
- <type>xml</type>
- <classifier>config</classifier>
- </artifact>
- </artifacts>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
</project>
private final Map<InstanceIdentifier<NodeConnector>, TransmitPacketInput> nodeConnectorMap = new ConcurrentHashMap<>();
private final ScheduledFuture<?> scheduledSpeakerTask;
private final MacAddress addressDestionation;
- private OperStatus operationalStatus = OperStatus.RUN;
+ private volatile OperStatus operationalStatus = OperStatus.RUN;
public LLDPSpeaker(final PacketProcessingService packetProcessingService,
final MacAddress addressDestionation) {
+++ /dev/null
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.lldp.speaker.rev141023;
-
-import org.opendaylight.controller.config.api.DependencyResolver;
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.openflowplugin.applications.lldpspeaker.LLDPSpeaker;
-import org.opendaylight.openflowplugin.applications.lldpspeaker.NodeConnectorInventoryEventTranslator;
-import org.opendaylight.openflowplugin.applications.lldpspeaker.OperationalStatusChangeService;
-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.packet.service.rev130709.PacketProcessingService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class LLDPSpeakerModule extends AbstractLLDPSpeakerModule {
- private static final Logger LOG = LoggerFactory
- .getLogger(LLDPSpeakerModule.class);
-
- public LLDPSpeakerModule(ModuleIdentifier identifier,
- DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public LLDPSpeakerModule(ModuleIdentifier identifier,
- DependencyResolver dependencyResolver, LLDPSpeakerModule oldModule,
- AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public AutoCloseable createInstance() {
- LOG.trace("Creating LLDP speaker.");
-
- PacketProcessingService packetProcessingService = getRpcRegistryDependency()
- .getRpcService(PacketProcessingService.class);
- MacAddress macDestination = getAddressDestination();
-
- final LLDPSpeaker lldpSpeaker = new LLDPSpeaker(
- packetProcessingService, macDestination);
- final NodeConnectorInventoryEventTranslator eventTranslator = new NodeConnectorInventoryEventTranslator(
- getDataBrokerDependency(), lldpSpeaker);
-
- OperationalStatusChangeService operationalStatusChangeService = new OperationalStatusChangeService(
- lldpSpeaker);
- final BindingAwareBroker.RpcRegistration<LldpSpeakerService> statusServiceRegistration =
- getRpcRegistryDependency().addRpcImplementation(LldpSpeakerService.class, operationalStatusChangeService);
-
- return new AutoCloseable() {
- @Override
- public void close() {
- LOG.trace("Closing LLDP speaker.");
- eventTranslator.close();
- lldpSpeaker.close();
- statusServiceRegistration.close();
- }
- };
- }
-
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: lldp-speaker yang module local name: lldp-speaker
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Thu Oct 23 10:01:14 MSK 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.lldp.speaker.rev141023;
-public class LLDPSpeakerModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.lldp.speaker.rev141023.AbstractLLDPSpeakerModuleFactory {
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2014 Pacnet 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
- -->
-
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-
-<snapshot>
- <configuration>
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:applications:lldp-speaker">prefix:lldp-speaker</type>
- <name>lldp-speaker</name>
- <data-broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
- <name>binding-data-broker</name>
- </data-broker>
- <rpc-registry>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
- <name>binding-rpc-broker</name>
- </rpc-registry>
- <address-destination>01:23:00:00:00:01</address-destination>
- </module>
-
- </modules>
- </data>
- </configuration>
-
- <required-capabilities>
- <capability>urn:opendaylight:flow:inventory?module=flow-node-inventory&revision=2013-08-19</capability>
- <capability>urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24</capability>
- <capability>urn:opendaylight:inventory?module=opendaylight-inventory&revision=2013-08-19</capability>
- <capability>urn:opendaylight:packet:service?module=packet-processing&revision=2013-07-09</capability>
- <capability>urn:opendaylight:flow:types:port?module=opendaylight-port-types&revision=2013-09-25</capability>
- </required-capabilities>
-</snapshot>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
+
+ <odl:clustered-app-config id="lldpSpeakerConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.lldp.speaker.config.rev160512.LldpSpeakerConfig">
+ <odl:default-config><![CDATA[
+ <lldp-speaker-config xmlns="urn:opendaylight:params:xml:ns:yang:openflow:applications:lldp-speaker:config">
+ <address-destination>01:23:00:00:00:01</address-destination>
+ </lldp-speaker-config>
+ ]]></odl:default-config>
+ </odl:clustered-app-config>
+
+ <odl:rpc-service id="packetProcessingService"
+ interface="org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService"/>
+
+ <bean id="lldpSpeaker" class="org.opendaylight.openflowplugin.applications.lldpspeaker.LLDPSpeaker"
+ destroy-method="close">
+ <argument ref="packetProcessingService"/>
+ <argument>
+ <bean factory-ref="lldpSpeakerConfig" factory-method="getAddressDestination"/>
+ </argument>
+ </bean>
+
+ <bean id="nodeConnectorEventTranslator" class="org.opendaylight.openflowplugin.applications.lldpspeaker.NodeConnectorInventoryEventTranslator"
+ destroy-method="close">
+ <argument ref="dataBroker"/>
+ <argument>
+ <array>
+ <ref component-id="lldpSpeaker"/>
+ </array>
+ </argument>
+ </bean>
+
+ <bean id="operationalStatusChangeService" class="org.opendaylight.openflowplugin.applications.lldpspeaker.OperationalStatusChangeService">
+ <argument ref="lldpSpeaker"/>
+ </bean>
+
+ <odl:rpc-implementation ref="operationalStatusChangeService"/>
+</blueprint>
\ No newline at end of file
--- /dev/null
+module lldp-speaker-config {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:openflow:applications:lldp-speaker:config";
+ prefix "lldp-speaker-config";
+
+ import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
+
+ description
+ "Configuration for LLDP speaker application.";
+
+ revision "2016-05-12" {
+ description
+ "Initial revision.";
+ }
+
+ container lldp-speaker-config {
+ leaf address-destination {
+ type yang:mac-address;
+ mandatory true;
+ }
+ }
+}
\ No newline at end of file
yang-version 1;
namespace "urn:opendaylight:params:xml:ns:yang:openflow:applications:lldp-speaker";
prefix "lldp-speaker";
- import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
- import config {prefix config; revision-date 2013-04-05;}
- import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28;}
- import rpc-context { prefix rpcx; revision-date 2013-06-17; }
-
description
"Application that send LLDPDU frames to all Openflow switch ports.";
"Initial revision";
}
- identity lldp-speaker {
- base "config:module-type";
- config:java-name-prefix LLDPSpeaker;
- }
-
typedef oper-status {
type enumeration {
enum STANDBY {
}
}
- augment "/config:modules/config:module/config:configuration" {
- case lldp-speaker {
- when "/config:modules/config:module/config:type = 'lldp-speaker'";
- container rpc-registry {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity mdsal:binding-rpc-registry;
- }
- }
- }
- container data-broker {
- uses config:service-ref {
- refine type {
- mandatory false;
- config:required-identity mdsal:binding-async-data-broker;
- }
- }
- }
- leaf address-destination {
- type yang:mac-address;
- }
- }
- }
-
rpc change-operational-status {
input {
leaf operational-status {
}
}
}
-
-
}
<version>0.3.0-SNAPSHOT</version>
</parent>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>old-notification-supplier</artifactId>
+ <artifactId>notification-supplier</artifactId>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<configuration>
<artifacts>
<artifact>
- <file>${project.build.directory}/classes/initial/73-old-notification-supplier.xml</file>
+ <file>${project.build.directory}/classes/initial/73-notification-supplier.xml</file>
<type>xml</type>
<classifier>config</classifier>
</artifact>
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.openflowplugin.applications.old.notification.supplier;
+package org.opendaylight.openflowplugin.applications.notification.supplier;
/**
* Project module provider interface representation
*/
-public interface OldNotifProvider extends AutoCloseable {
+public interface NotificationProvider extends AutoCloseable {
/**
- * Method is responsible for initialization and registration all Old Notification Suppliers
+ * Method is responsible for initialization and registration all Notification Suppliers
* followed by settings from ConfigSubsystem
*/
void start();
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.NodeConnectorNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.NodeNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.FlowNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.GroupNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.MeterNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.stat.FlowStatNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.stat.FlowTableStatNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.stat.GroupStatNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.stat.MeterStatNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.stat.NodeConnectorStatNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.stat.QueueStatNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.notification.supplier.tools.NotificationProviderConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.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.statistics.rev130819.FlowsStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdate;
+
+/**
+ * Provider Implementation
+ */
+public class NotificationProviderImpl implements NotificationProvider {
+
+ private final DataBroker db;
+ private final NotificationProviderConfig config;
+ private final NotificationProviderService nps;
+
+ /* Supplier List property help for easy close method implementation and testing */
+ private List<NotificationSupplierDefinition<?>> supplierList;
+ private NotificationSupplierForItemRoot<FlowCapableNode, NodeUpdated, NodeRemoved> nodeSupp;
+ private NotificationSupplierForItemRoot<FlowCapableNodeConnector, NodeConnectorUpdated, NodeConnectorRemoved> connectorSupp;
+ private NotificationSupplierForItem<Flow, FlowAdded, FlowUpdated, FlowRemoved> flowSupp;
+ private NotificationSupplierForItem<Meter, MeterAdded, MeterUpdated, MeterRemoved> meterSupp;
+ private NotificationSupplierForItem<Group, GroupAdded, GroupUpdated, GroupRemoved> groupSupp;
+ private NotificationSupplierForItemStat<FlowCapableNodeConnectorStatistics, NodeConnectorStatisticsUpdate> connectorStatSupp;
+ private NotificationSupplierForItemStat<FlowStatistics, FlowsStatisticsUpdate> flowStatSupp;
+ private NotificationSupplierForItemStat<FlowTableStatistics, FlowTableStatisticsUpdate> flowTableStatSupp;
+ private NotificationSupplierForItemStat<MeterStatistics, MeterStatisticsUpdated> meterStatSupp;
+ private NotificationSupplierForItemStat<GroupStatistics, GroupStatisticsUpdated> groupStatSupp;
+ private NotificationSupplierForItemStat<FlowCapableNodeConnectorQueueStatisticsData, QueueStatisticsUpdate> queueStatSupp;
+
+ /**
+ * Provider constructor set all needed final parameters
+ *
+ * @param config - Configuration Object
+ * @param nps - notifProviderService
+ * @param db - dataBroker
+ */
+ public NotificationProviderImpl(final NotificationProviderConfig config,
+ final NotificationProviderService nps, final DataBroker db) {
+ this.config = Preconditions.checkNotNull(config);
+ this.db = Preconditions.checkNotNull(db);
+ this.nps = Preconditions.checkNotNull(nps);
+ }
+
+ @Override
+ public void start() {
+ nodeSupp = new NodeNotificationSupplierImpl(nps, db);
+ connectorSupp = new NodeConnectorNotificationSupplierImpl(nps, db);
+ flowSupp = config.isFlowSupport() ? new FlowNotificationSupplierImpl(nps, db) : null;
+ meterSupp = config.isMeterSupport() ? new MeterNotificationSupplierImpl(nps, db) : null;
+ groupSupp = config.isGroupSupport() ? new GroupNotificationSupplierImpl(nps, db) : null;
+ connectorStatSupp = config.isNodeConnectorStatSupport() ? new NodeConnectorStatNotificationSupplierImpl(nps, db) : null;
+ flowStatSupp = config.isFlowStatSupport() ? new FlowStatNotificationSupplierImpl(nps, db) : null;
+ flowTableStatSupp = config.isFlowTableStatSupport() ? new FlowTableStatNotificationSupplierImpl(nps, db) : null;
+ meterStatSupp = config.isMeterStatSupport() ? new MeterStatNotificationSupplierImpl(nps, db) : null;
+ groupStatSupp = config.isGroupStatSupport() ? new GroupStatNotificationSupplierImpl(nps, db) : null;
+ queueStatSupp = config.isQueueStatSupport() ? new QueueStatNotificationSupplierImpl(nps, db) : null;
+
+ supplierList = new ArrayList<>(Arrays.asList(nodeSupp, connectorSupp, flowSupp, meterSupp, groupSupp,
+ connectorStatSupp, flowStatSupp, flowTableStatSupp, meterStatSupp, groupStatSupp, queueStatSupp));
+ }
+
+ @Override
+ public void close() throws Exception {
+ for (NotificationSupplierDefinition<?> supplier : supplierList) {
+ if (supplier != null) {
+ supplier.close();
+ supplier = null;
+ }
+ }
+ }
+
+ @VisibleForTesting
+ List<NotificationSupplierDefinition<?>> getSupplierList() {
+ return supplierList;
+ }
+}
+
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.openflowplugin.applications.old.notification.supplier;
+package org.opendaylight.openflowplugin.applications.notification.supplier;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
- * Default definition for every Old Notification Supplier. Migration from old notification
+ * Default definition for every Notification Supplier. Migration from notification
* to {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener} has one
* keyed component - WildCarded Path which represent a changes checker in DataStoreTreeNode
*
* @param <O> - {@link DataObject} represent Data Tree Item from DataStore
*/
-public interface OldNotifSupplierDefinition<O extends DataObject> extends AutoCloseable, DataChangeListener {
+public interface NotificationSupplierDefinition<O extends DataObject> extends AutoCloseable, DataChangeListener {
/**
* Method return wildCardPath for Listener registration and for identify
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+/**
+ * Supplier Item contracts definition for every Notification. All items are described
+ * by three notifications. Notification for Create, Update and Delete. So interface
+ * has to contain three methods for every Notification.
+ *
+ * @param <O> - data tree item Object
+ * @param <C> - Create notification
+ * @param <U> - Update notification
+ * @param <D> - Delete notification
+ */
+public interface NotificationSupplierForItem<O extends DataObject,
+ C extends Notification,
+ U extends Notification,
+ D extends Notification>
+ extends NotificationSupplierDefinition<O> {
+
+ /**
+ * Method produces relevant addItem kind of {@link Notification} from
+ * data tree item identified by {@link InstanceIdentifier} path.
+ *
+ * @param o - Data Tree Item object
+ * @param path - Identifier of Data Tree Item
+ * @return {@link Notification} - relevant API contract Notification
+ */
+ C createNotification(O o, InstanceIdentifier<O> path);
+
+ /**
+ * Method produces relevant updateItem kind of {@link Notification} from
+ * data tree item identified by {@link InstanceIdentifier} path.
+ *
+ * @param o - Data Tree Item object
+ * @param path - Identifier of Data Tree Item
+ * @return {@link Notification} - relevant API contract Notification
+ */
+ U updateNotification(O o, InstanceIdentifier<O> path);
+
+ /**
+ * Method produces relevant deleteItem kind of {@link Notification} from
+ * path {@link InstanceIdentifier} to deleted item.
+ *
+ * @param path - Identifier of Data Tree Item
+ * @return {@link Notification} - relevant API contract Notification
+ */
+ D deleteNotification(InstanceIdentifier<O> path);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+/**
+ * Supplier Root Item contracts definition for every Notification. All root items
+ * are described by two notifications. Notification for Create and Delete.
+ * So interface has to contain two methods for relevant Notification.
+ *
+ * @param <O> - data tree item Object
+ * @param <C> - Create notification
+ * @param <D> - Delete notification
+ */
+public interface NotificationSupplierForItemRoot<O extends DataObject,
+ C extends Notification,
+ D extends Notification>
+ extends NotificationSupplierDefinition<O> {
+
+ /**
+ * Method produces relevant addItem kind of {@link Notification} from
+ * data tree item identified by {@link InstanceIdentifier} path.
+ *
+ * @param o - Data Tree Item object
+ * @param path - Identifier of Data Tree Item
+ * @return {@link Notification} - relevant API contract Notification
+ */
+ C createNotification(O o, InstanceIdentifier<O> path);
+
+ /**
+ * Method produces relevant deleteItem kind of {@link Notification} from
+ * path {@link InstanceIdentifier} to deleted item.
+ *
+ * @param path - Identifier of Data Tree Item
+ * @return {@link Notification} - relevant API contract Notification
+ */
+ D deleteNotification(InstanceIdentifier<O> path);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+/**
+ * Notifications for Statistics have little bit different case,
+ * because it looks like they have response for create and update.
+ * But follow the statistics internal implementation processing
+ * is talks only about create event.
+ *
+ * @param <O> - data tree item Object
+ * @param <N> - Statistics Notification
+ */
+public interface NotificationSupplierForItemStat<O extends DataObject, N extends Notification>
+ extends NotificationSupplierDefinition<O> {
+
+
+ /**
+ * Method produces relevant Statistics kind of {@link Notification} from statistics
+ * data tree item identified by {@link InstanceIdentifier} path.
+ *
+ * @param o - Statistics Data Tree Item
+ * @param path - Identifier of Data Tree Item
+ * @return {@link Notification} - relevant API contract Notification
+ */
+ N createNotification(O o, InstanceIdentifier<O> path);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.applications.notification.supplier.NotificationSupplierDefinition;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Public abstract basic Supplier implementation contains code for a make Supplier instance,
+ * registration Supplier like {@link org.opendaylight.controller.md.sal.binding.api.DataChangeListener}
+ * and close method. In additional case, it contains help methods for all Supplier implementations.
+ *
+ * @param <O> - data tree item Object extends {@link DataObject}
+ */
+public abstract class AbstractNotificationSupplierBase<O extends DataObject> implements
+ NotificationSupplierDefinition<O> {
+
+ protected final Class<O> clazz;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+ /**
+ * Default constructor for all Notification Supplier implementation
+ *
+ * @param db - {@link DataBroker}
+ * @param clazz - API contract class extended {@link DataObject}
+ */
+ public AbstractNotificationSupplierBase(final DataBroker db, final Class<O> clazz) {
+ Preconditions.checkArgument(db != null, "DataBroker can not be null!");
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, getWildCardPath(), this,
+ DataChangeScope.BASE);
+ this.clazz = clazz;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ listenerRegistration.close();
+ listenerRegistration = null;
+ }
+ }
+
+ /**
+ * Method returns a wildCard {@link InstanceIdentifier} for {@link Node} from inventory
+ * because this path is a base for every OF paths.
+ *
+ * @return WildCarded InstanceIdentifier for Node
+ */
+ protected static InstanceIdentifier<Node> getNodeWildII() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class);
+ }
+
+ /**
+ * Method returns a keyed {@link InstanceIdentifier} for {@link Node} from inventory
+ * because this path is a base for every OF paths.
+ *
+ * @param ii - key for keyed {@link Node} {@link InstanceIdentifier}
+ * @return Keyed InstanceIdentifier for Node
+ */
+ protected static KeyedInstanceIdentifier<Node, NodeKey> getNodeII(final InstanceIdentifier<?> ii) {
+ final NodeKey key = ii.firstKeyOf(Node.class, NodeKey.class);
+ Preconditions.checkArgument(key != null);
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, key);
+ }
+
+ /**
+ * @param path pointer to element
+ * @return extracted {@link NodeKey} and wrapped in {@link NodeRef}
+ */
+ public static NodeRef createNodeRef(InstanceIdentifier<?> path) {
+ final InstanceIdentifier<Node> nodePath = Preconditions.checkNotNull(path.firstIdentifierOf(Node.class));
+ return new NodeRef(nodePath);
+ }
+
+ /**
+ * @param path pointer to element
+ * @return extracted {@link NodeId}
+ */
+ public static NodeId getNodeId(InstanceIdentifier<?> path) {
+ final NodeKey nodeKey = Preconditions.checkNotNull(path.firstKeyOf(Node.class, NodeKey.class));
+ return nodeKey.getId();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Map.Entry;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.NotificationSupplierForItemRoot;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+/**
+ * Class is package protected abstract implementation for all Root Items
+ * Notification Suppliers
+ *
+ * @param <O> - data tree item Object
+ * @param <C> - Create notification
+ * @param <D> - Delete notification
+ */
+abstract class AbstractNotificationSupplierForItemRoot<O extends DataObject,
+ C extends Notification,
+ D extends Notification>
+ extends AbstractNotificationSupplierBase<O>
+ implements NotificationSupplierForItemRoot<O, C, D> {
+
+ private final NotificationProviderService notificationProviderService;
+
+ /**
+ * Default constructor for all Root Item Notification Supplier implementation
+ *
+ * @param notificationProviderService - notification publisher
+ * @param db - DataBroker for DataChangeEvent registration
+ * @param clazz - Statistics Notification Class
+ */
+ public AbstractNotificationSupplierForItemRoot(final NotificationProviderService notificationProviderService, final DataBroker db,
+ final Class<O> clazz) {
+ super(db, clazz);
+ this.notificationProviderService = Preconditions.checkNotNull(notificationProviderService);
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ Preconditions.checkArgument(change != null, "ChangeEvent can not be null!");
+ if (change.getCreatedData() != null && ! (change.getCreatedData().isEmpty())) {
+ for (final Entry<InstanceIdentifier<?>, DataObject> createDataObj : change.getCreatedData().entrySet()) {
+ if (clazz.isAssignableFrom(createDataObj.getKey().getTargetType())) {
+ final InstanceIdentifier<O> ii = createDataObj.getKey().firstIdentifierOf(clazz);
+ final C notif = createNotification((O) createDataObj.getValue(), ii);
+ if (notif != null) {
+ notificationProviderService.publish(notif);
+ }
+ }
+ }
+ }
+
+ if (change.getRemovedPaths() != null && !(change.getRemovedPaths().isEmpty())) {
+ for (final InstanceIdentifier<?> deleteDataPath : change.getRemovedPaths()) {
+ if (clazz.isAssignableFrom(deleteDataPath.getTargetType())) {
+ final D notif = deleteNotification(deleteDataPath.firstIdentifierOf(clazz));
+ if (notif != null) {
+ notificationProviderService.publish(notif);
+ }
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemovedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link FlowCapableNodeConnector} data object
+ * and {@link NodeConnectorUpdated} and {@link NodeConnectorRemoved} notifications.
+ */
+public class NodeConnectorNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItemRoot<FlowCapableNodeConnector, NodeConnectorUpdated, NodeConnectorRemoved> {
+
+ private static final InstanceIdentifier<FlowCapableNodeConnector> wildCardedInstanceIdent = getNodeWildII().child(NodeConnector.class).augmentation(FlowCapableNodeConnector.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public NodeConnectorNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, FlowCapableNodeConnector.class);
+ }
+
+ @Override
+ public InstanceIdentifier<FlowCapableNodeConnector> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public NodeConnectorUpdated createNotification(final FlowCapableNodeConnector o,
+ final InstanceIdentifier<FlowCapableNodeConnector> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+ final NodeConnectorUpdatedBuilder notifBuilder = new NodeConnectorUpdatedBuilder();
+ final FlowCapableNodeConnectorUpdatedBuilder connNotifBuilder = new FlowCapableNodeConnectorUpdatedBuilder(o);
+ notifBuilder.setId(path.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId());
+ notifBuilder.setNodeConnectorRef(new NodeConnectorRef(path));
+ notifBuilder.addAugmentation(FlowCapableNodeConnectorUpdated.class, connNotifBuilder.build());
+ return notifBuilder.build();
+ }
+
+ @Override
+ public NodeConnectorRemoved deleteNotification(final InstanceIdentifier<FlowCapableNodeConnector> path) {
+ Preconditions.checkArgument(path != null);
+ final NodeConnectorRemovedBuilder notifBuilder = new NodeConnectorRemovedBuilder();
+ notifBuilder.setNodeConnectorRef(new NodeConnectorRef(path));
+ return notifBuilder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemovedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link FlowCapableNode} data object
+ * and {@link NodeUpdated} and {@link NodeRemoved} notifications.
+ */
+public class NodeNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItemRoot<FlowCapableNode, NodeUpdated, NodeRemoved> {
+
+ private static final InstanceIdentifier<FlowCapableNode> wildCardedInstanceIdent = getNodeWildII().augmentation(FlowCapableNode.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public NodeNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, FlowCapableNode.class);
+ }
+
+ @Override
+ public InstanceIdentifier<FlowCapableNode> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public NodeUpdated createNotification(final FlowCapableNode o, final InstanceIdentifier<FlowCapableNode> ii) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(ii != null);
+ final FlowCapableNodeUpdatedBuilder flowNodeNotifBuilder = new FlowCapableNodeUpdatedBuilder(o);
+ final NodeUpdatedBuilder notifBuilder = new NodeUpdatedBuilder();
+ notifBuilder.setId(ii.firstKeyOf(Node.class, NodeKey.class).getId());
+ notifBuilder.setNodeRef(new NodeRef(getNodeII(ii)));
+ notifBuilder.addAugmentation(FlowCapableNodeUpdated.class, flowNodeNotifBuilder.build());
+ return notifBuilder.build();
+ }
+
+ @Override
+ public NodeRemoved deleteNotification(final InstanceIdentifier<FlowCapableNode> path) {
+ Preconditions.checkArgument(path != null);
+ final NodeRemovedBuilder delNodeNotifBuilder = new NodeRemovedBuilder();
+ delNodeNotifBuilder.setNodeRef(new NodeRef(path));
+ return delNodeNotifBuilder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item;
+
+import com.google.common.base.Preconditions;
+import java.util.Map.Entry;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.NotificationSupplierForItem;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.AbstractNotificationSupplierBase;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+/**
+ * Class is package protected abstract implementation for all Old Root Items
+ * Notification Suppliers
+ *
+ * @param <O> - data tree item Object
+ * @param <C> - Create notification
+ * @param <U> - Update notification
+ * @param <D> - Delete notification
+ */
+abstract class AbstractNotificationSupplierForItem<O extends DataObject,
+ C extends Notification,
+ U extends Notification,
+ D extends Notification>
+ extends AbstractNotificationSupplierBase<O>
+ implements NotificationSupplierForItem<O, C, U, D> {
+
+ private final NotificationProviderService notificationProviderService;
+
+ /**
+ * Default constructor for all item Notification Supplier implementation
+ *
+ * @param notifProviderService - notification publisher
+ * @param db - DataBroker for DataChangeEvent registration
+ * @param clazz - Statistics Notification Class
+ */
+ public AbstractNotificationSupplierForItem(final NotificationProviderService notifProviderService, final DataBroker db,
+ final Class<O> clazz) {
+ super(db, clazz);
+ this.notificationProviderService = Preconditions.checkNotNull(notifProviderService);
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ Preconditions.checkArgument(change != null, "ChangeEvent can not be null!");
+ if (change.getCreatedData() != null && !(change.getCreatedData().isEmpty())) {
+ for (final Entry<InstanceIdentifier<?>, DataObject> createDataObj : change.getCreatedData().entrySet()) {
+ if (clazz.isAssignableFrom(createDataObj.getKey().getTargetType())) {
+ final InstanceIdentifier<O> ii = createDataObj.getKey().firstIdentifierOf(clazz);
+ final C notif = createNotification((O) createDataObj.getValue(), ii);
+ if (notif != null) {
+ notificationProviderService.publish(notif);
+ }
+ }
+ }
+ }
+
+ if (change.getUpdatedData() != null && !(change.getUpdatedData().isEmpty())) {
+ for (final Entry<InstanceIdentifier<?>, DataObject> updateDataObj : change.getUpdatedData().entrySet()) {
+ if (clazz.isAssignableFrom(updateDataObj.getKey().getTargetType())) {
+ final InstanceIdentifier<O> ii = updateDataObj.getKey().firstIdentifierOf(clazz);
+ final U notif = updateNotification((O) updateDataObj.getValue(), ii);
+ if (notif != null) {
+ notificationProviderService.publish(notif);
+ }
+ }
+ }
+ }
+
+ if (change.getRemovedPaths() != null && !(change.getRemovedPaths().isEmpty())) {
+ for (final InstanceIdentifier<?> deleteDataPath : change.getRemovedPaths()) {
+ if (clazz.isAssignableFrom(deleteDataPath.getTargetType())) {
+ final D notif = deleteNotification(deleteDataPath.firstIdentifierOf(clazz));
+ if (notif != null) {
+ notificationProviderService.publish(notif);
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link Flow} data object
+ * and {@link FlowAdded}, {@link FlowUpdated} and {@link FlowRemoved} notifications.
+ */
+public class FlowNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItem<Flow, FlowAdded, FlowUpdated, FlowRemoved> {
+
+ private static final InstanceIdentifier<Flow> wildCardedInstanceIdent = getNodeWildII().augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public FlowNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, Flow.class);
+ }
+
+ @Override
+ public InstanceIdentifier<Flow> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public FlowAdded createNotification(final Flow o, final InstanceIdentifier<Flow> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+ final FlowAddedBuilder builder = new FlowAddedBuilder(o);
+ builder.setFlowRef(new FlowRef(path));
+ builder.setNode(createNodeRef(path));
+ return builder.build();
+ }
+
+ @Override
+ public FlowUpdated updateNotification(final Flow o, final InstanceIdentifier<Flow> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+ final FlowUpdatedBuilder builder = new FlowUpdatedBuilder(o);
+ builder.setFlowRef(new FlowRef(path));
+ builder.setNode(createNodeRef(path));
+ return builder.build();
+ }
+
+ @Override
+ public FlowRemoved deleteNotification(final InstanceIdentifier<Flow> path) {
+ Preconditions.checkArgument(path != null);
+ final FlowRemovedBuilder builder = new FlowRemovedBuilder();
+ builder.setFlowRef(new FlowRef(path));
+ builder.setNode(createNodeRef(path));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAddedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemovedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link Group} data object
+ * and {@link GroupAdded}, {@link GroupUpdated} and {@link GroupRemoved} notifications.
+ */
+public class GroupNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItem<Group, GroupAdded, GroupUpdated, GroupRemoved> {
+
+ private static final InstanceIdentifier<Group> wildCardedInstanceIdent = getNodeWildII().augmentation(FlowCapableNode.class).child(Group.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public GroupNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, Group.class);
+ }
+
+ @Override
+ public InstanceIdentifier<Group> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public GroupAdded createNotification(final Group o, final InstanceIdentifier<Group> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+ final GroupAddedBuilder builder = new GroupAddedBuilder(o);
+ builder.setGroupRef(new GroupRef(path));
+ builder.setNode(createNodeRef(path));
+ return builder.build();
+ }
+
+ @Override
+ public GroupUpdated updateNotification(final Group o, final InstanceIdentifier<Group> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+ final GroupUpdatedBuilder builder = new GroupUpdatedBuilder(o);
+ builder.setGroupRef(new GroupRef(path));
+ builder.setNode(createNodeRef(path));
+ return builder.build();
+ }
+
+ @Override
+ public GroupRemoved deleteNotification(final InstanceIdentifier<Group> path) {
+ Preconditions.checkArgument(path != null);
+ final GroupRemovedBuilder builder = new GroupRemovedBuilder();
+ builder.setGroupId(path.firstKeyOf(Group.class, GroupKey.class).getGroupId());
+ builder.setGroupRef(new GroupRef(path));
+ builder.setNode(createNodeRef(path));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterAddedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterRemovedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link Meter} data object
+ * and {@link MeterAdded}, {@link MeterUpdated} and {@link MeterRemoved} notifications.
+ */
+public class MeterNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItem<Meter, MeterAdded, MeterUpdated, MeterRemoved> {
+
+ private static final InstanceIdentifier<Meter> wildCardedInstanceIdent = getNodeWildII().augmentation(FlowCapableNode.class).child(Meter.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public MeterNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, Meter.class);
+ }
+
+ @Override
+ public InstanceIdentifier<Meter> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public MeterAdded createNotification(final Meter o, final InstanceIdentifier<Meter> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+ final MeterAddedBuilder builder = new MeterAddedBuilder(o);
+ builder.setMeterRef(new MeterRef(path));
+ builder.setNode(createNodeRef(path));
+ return builder.build();
+ }
+
+ @Override
+ public MeterUpdated updateNotification(final Meter o, final InstanceIdentifier<Meter> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+ final MeterUpdatedBuilder builder = new MeterUpdatedBuilder(o);
+ builder.setMeterRef(new MeterRef(path));
+ builder.setNode(createNodeRef(path));
+ return builder.build();
+ }
+
+ @Override
+ public MeterRemoved deleteNotification(final InstanceIdentifier<Meter> path) {
+ Preconditions.checkArgument(path != null);
+ final MeterRemovedBuilder builder = new MeterRemovedBuilder();
+ builder.setMeterId(path.firstKeyOf(Meter.class, MeterKey.class).getMeterId());
+ builder.setMeterRef(new MeterRef(path));
+ builder.setNode(createNodeRef(path));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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 contains OF Items (Flow, Group, Meter ...) notification listener/supplier implementations
+ */
+package org.opendaylight.openflowplugin.applications.notification.supplier.impl.item;
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import com.google.common.base.Preconditions;
+import java.util.Map.Entry;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.NotificationSupplierForItemStat;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.AbstractNotificationSupplierBase;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+/**
+ * Class is package protected abstract implementation for all Old Statistics
+ * Notification Suppliers
+ *
+ * @param <O> - Statistics {@link DataObject}
+ * @param <N> - Statistics Notification
+ */
+abstract class AbstractNotificationSupplierForItemStat<O extends DataObject,
+ N extends Notification>
+ extends AbstractNotificationSupplierBase<O>
+ implements NotificationSupplierForItemStat<O, N> {
+
+ private final NotificationProviderService notifProviderService;
+
+ /**
+ * Default constructor for all Statistic Notification Supplier implementation
+ *
+ * @param notifProviderService - notification publisher
+ * @param db - DataBroker for DataChangeEvent registration
+ * @param clazz - Statistics Notification Class
+ */
+ public AbstractNotificationSupplierForItemStat(final NotificationProviderService notifProviderService,
+ final DataBroker db, final Class<O> clazz) {
+ super(db, clazz);
+ this.notifProviderService = Preconditions.checkNotNull(notifProviderService);
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ Preconditions.checkArgument(change != null, "ChangeEvent can not be null!");
+ if (change.getCreatedData() != null && !(change.getCreatedData().isEmpty())) {
+ for (final Entry<InstanceIdentifier<?>, DataObject> createDataObj : change.getCreatedData().entrySet()) {
+ if (clazz.isAssignableFrom(createDataObj.getKey().getTargetType())) {
+ final InstanceIdentifier<O> ii = createDataObj.getKey().firstIdentifierOf(clazz);
+ final N notif = createNotification((O) createDataObj.getValue(), ii);
+ if (notif != null) {
+ notifProviderService.publish(notif);
+ }
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link FlowStatistics} data object
+ * and {@link FlowsStatisticsUpdate} notification.
+ */
+public class FlowStatNotificationSupplierImpl extends AbstractNotificationSupplierForItemStat<FlowStatistics, FlowsStatisticsUpdate> {
+
+ private static final InstanceIdentifier<FlowStatistics> wildCardedInstanceIdent =
+ getNodeWildII().augmentation(FlowCapableNode.class).child(Table.class)
+ .child(Flow.class).augmentation(FlowStatisticsData.class).child(FlowStatistics.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public FlowStatNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, FlowStatistics.class);
+ }
+
+ @Override
+ public InstanceIdentifier<FlowStatistics> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public FlowsStatisticsUpdate createNotification(final FlowStatistics o, final InstanceIdentifier<FlowStatistics> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+
+ final FlowAndStatisticsMapListBuilder fsmlBuilder = new FlowAndStatisticsMapListBuilder(o);
+ fsmlBuilder.setFlowId(new FlowId(path.firstKeyOf(Flow.class, FlowKey.class).getId().getValue()));
+
+ final FlowsStatisticsUpdateBuilder builder = new FlowsStatisticsUpdateBuilder();
+ builder.setId(getNodeId(path));
+ builder.setMoreReplies(Boolean.FALSE);
+ // NOTE : fix if it needs, but we have to ask DataStore for the NodeConnector list
+ builder.setNodeConnector(Collections.<NodeConnector>emptyList());
+ builder.setFlowAndStatisticsMapList(Collections.singletonList(fsmlBuilder.build()));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link FlowTableStatistics} data object
+ * and {@link FlowTableStatisticsUpdate} notification.
+ */
+public class FlowTableStatNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItemStat<FlowTableStatistics, FlowTableStatisticsUpdate> {
+
+ private static final InstanceIdentifier<FlowTableStatistics> wildCardedInstanceIdent =
+ getNodeWildII().augmentation(FlowCapableNode.class).child(Table.class)
+ .augmentation(FlowTableStatisticsData.class).child(FlowTableStatistics.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public FlowTableStatNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, FlowTableStatistics.class);
+ }
+
+ @Override
+ public InstanceIdentifier<FlowTableStatistics> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public FlowTableStatisticsUpdate createNotification(final FlowTableStatistics o,
+ final InstanceIdentifier<FlowTableStatistics> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+
+ final FlowTableAndStatisticsMapBuilder ftsmBuilder = new FlowTableAndStatisticsMapBuilder(o);
+ ftsmBuilder.setKey(new FlowTableAndStatisticsMapKey(new TableId(path.firstKeyOf(Table.class, TableKey.class).getId())));
+
+ final FlowTableStatisticsUpdateBuilder builder = new FlowTableStatisticsUpdateBuilder();
+ builder.setId(getNodeId(path));
+ builder.setMoreReplies(Boolean.FALSE);
+ // NOTE : fix if it needs, but we have to ask DataStore for the NodeConnector list
+ builder.setNodeConnector(Collections.<NodeConnector>emptyList());
+ builder.setFlowTableAndStatisticsMap(Collections.singletonList(ftsmBuilder.build()));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link GroupStatistics} data object
+ * and {@link GroupStatisticsUpdated} notification.
+ */
+public class GroupStatNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItemStat<GroupStatistics, GroupStatisticsUpdated> {
+
+ private static final InstanceIdentifier<GroupStatistics> wildCardedInstanceIdent =
+ getNodeWildII().augmentation(FlowCapableNode.class).child(Group.class)
+ .augmentation(NodeGroupStatistics.class).child(GroupStatistics.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public GroupStatNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, GroupStatistics.class);
+ }
+
+ @Override
+ public InstanceIdentifier<GroupStatistics> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public GroupStatisticsUpdated createNotification(final GroupStatistics o,
+ final InstanceIdentifier<GroupStatistics> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+
+ final GroupStatisticsUpdatedBuilder builder = new GroupStatisticsUpdatedBuilder();
+ builder.setId(getNodeId(path));
+ builder.setMoreReplies(Boolean.FALSE);
+ // TODO : fix if it needs, but we have to ask DataStore for the NodeConnector list
+ builder.setNodeConnector(Collections.<NodeConnector>emptyList());
+ builder.setGroupStats(Collections.singletonList(new GroupStatsBuilder(o).build()));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStatsBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link MeterStatistics} data object
+ * and {@link MeterStatisticsUpdated} notification.
+ */
+public class MeterStatNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItemStat<MeterStatistics, MeterStatisticsUpdated> {
+
+ private static final InstanceIdentifier<MeterStatistics> wildCardedInstanceIdent =
+ getNodeWildII().augmentation(FlowCapableNode.class).child(Meter.class)
+ .augmentation(NodeMeterStatistics.class).child(MeterStatistics.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public MeterStatNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, MeterStatistics.class);
+ }
+
+ @Override
+ public InstanceIdentifier<MeterStatistics> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public MeterStatisticsUpdated createNotification(final MeterStatistics o,
+ final InstanceIdentifier<MeterStatistics> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+
+ final MeterStatisticsUpdatedBuilder builder = new MeterStatisticsUpdatedBuilder();
+ builder.setId(getNodeId(path));
+ builder.setMoreReplies(Boolean.FALSE);
+ // TODO : fix if it needs, but we have to ask DataStore for the NodeConnector list
+ builder.setNodeConnector(Collections.<NodeConnector>emptyList());
+ builder.setMeterStats(Collections.singletonList(new MeterStatsBuilder(o).build()));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link FlowCapableNodeConnectorStatistics} data object
+ * and {@link NodeConnectorStatisticsUpdate} notification.
+ */
+public class NodeConnectorStatNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItemStat<FlowCapableNodeConnectorStatistics, NodeConnectorStatisticsUpdate> {
+
+ private static final InstanceIdentifier<FlowCapableNodeConnectorStatistics> wildCardedInstanceIdent =
+ getNodeWildII().child(NodeConnector.class)
+ .augmentation(FlowCapableNodeConnectorStatisticsData.class)
+ .child(FlowCapableNodeConnectorStatistics.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public NodeConnectorStatNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, FlowCapableNodeConnectorStatistics.class);
+ }
+
+ @Override
+ public InstanceIdentifier<FlowCapableNodeConnectorStatistics> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public NodeConnectorStatisticsUpdate createNotification(final FlowCapableNodeConnectorStatistics o,
+ final InstanceIdentifier<FlowCapableNodeConnectorStatistics> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+
+ final NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder();
+ final NodeConnectorKey ncKey = path.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
+ ncBuilder.setId(ncKey.getId());
+ ncBuilder.setKey(ncKey);
+
+ final NodeConnectorStatisticsUpdateBuilder builder = new NodeConnectorStatisticsUpdateBuilder();
+ builder.setId(getNodeId(path));
+ builder.setMoreReplies(Boolean.FALSE);
+ builder.setNodeConnector(Collections.singletonList(ncBuilder.build()));
+ builder.setNodeConnectorStatisticsAndPortNumberMap(Collections
+ .singletonList(new NodeConnectorStatisticsAndPortNumberMapBuilder(o).build()));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link FlowCapableNodeConnectorQueueStatisticsData} data object
+ * and {@link QueueStatisticsUpdate} notification.
+ */
+public class QueueStatNotificationSupplierImpl extends
+ AbstractNotificationSupplierForItemStat<FlowCapableNodeConnectorQueueStatisticsData, QueueStatisticsUpdate> {
+
+ private static final InstanceIdentifier<FlowCapableNodeConnectorQueueStatisticsData> wildCardedInstanceIdent =
+ getNodeWildII().child(NodeConnector.class)
+ .augmentation(FlowCapableNodeConnector.class).child(Queue.class)
+ .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class);
+
+ /**
+ * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+ *
+ * @param notifProviderService - {@link NotificationProviderService}
+ * @param db - {@link DataBroker}
+ */
+ public QueueStatNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+ super(notifProviderService, db, FlowCapableNodeConnectorQueueStatisticsData.class);
+ }
+
+ @Override
+ public InstanceIdentifier<FlowCapableNodeConnectorQueueStatisticsData> getWildCardPath() {
+ return wildCardedInstanceIdent;
+ }
+
+ @Override
+ public QueueStatisticsUpdate createNotification(final FlowCapableNodeConnectorQueueStatisticsData o,
+ final InstanceIdentifier<FlowCapableNodeConnectorQueueStatisticsData> path) {
+ Preconditions.checkArgument(o != null);
+ Preconditions.checkArgument(path != null);
+
+ final NodeConnectorBuilder connBuilder = new NodeConnectorBuilder();
+ final NodeConnectorKey key = path.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
+ connBuilder.setId(key.getId());
+ connBuilder.setKey(key);
+
+ final QueueIdAndStatisticsMapBuilder queueStatMapBuilder =
+ new QueueIdAndStatisticsMapBuilder(o.getFlowCapableNodeConnectorQueueStatistics());
+
+ final QueueStatisticsUpdateBuilder builder = new QueueStatisticsUpdateBuilder();
+ builder.setId(getNodeId(path));
+ builder.setMoreReplies(Boolean.FALSE);
+ builder.setQueueIdAndStatisticsMap(Collections.singletonList(queueStatMapBuilder.build()));
+ builder.setNodeConnector(Collections.singletonList(connBuilder.build()));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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 contains OF Statistics Items (Flow, Group, Meter ...) notification listener/supplier implementations
+ */
+package org.opendaylight.openflowplugin.applications.notification.supplier.impl.item.stat;
\ No newline at end of file
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.openflowplugin.applications.bulk.o.matic;
-
/**
- * Created by mirehak on 6/8/15.
+ * Package contains notification listener/supplier implementations
*/
-public interface BulkOMaticProvider extends AutoCloseable {
- // NOBODY
-}
+package org.opendaylight.openflowplugin.applications.notification.supplier.impl;
\ No newline at end of file
/**
* Base project package for a module Provider and base notification listener/supplier interface
*/
-package org.opendaylight.openflowplugin.applications.old.notification.supplier;
\ No newline at end of file
+package org.opendaylight.openflowplugin.applications.notification.supplier;
\ No newline at end of file
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.openflowplugin.applications.old.notification.supplier.tools;
+package org.opendaylight.openflowplugin.applications.notification.supplier.tools;
/**
* Class is designed as ConfigSubsitem settings holder
*/
-public class OldNotifProviderConfig {
+public class NotificationProviderConfig {
private final boolean flowSupport;
private final boolean meterSupport;
private final boolean queueStatSupport;
private final boolean flowStatSupport;
- private OldNotifProviderConfig(final OldNotifProviderConfigBuilder builder) {
+ private NotificationProviderConfig(final NotificationProviderConfigBuilder builder) {
this.flowSupport = builder.isFlowSupport();
this.meterSupport = builder.isMeterSupport();
this.groupSupport = builder.isGroupSupport();
return flowStatSupport;
}
- public static OldNotifProviderConfigBuilder builder() {
- return new OldNotifProviderConfigBuilder();
+ public static NotificationProviderConfigBuilder builder() {
+ return new NotificationProviderConfigBuilder();
}
- public static class OldNotifProviderConfigBuilder {
+ public static class NotificationProviderConfigBuilder {
private boolean flowSupport;
private boolean meterSupport;
private boolean groupSupport;
this.flowStatSupport = flowStatSupport;
}
- public OldNotifProviderConfig build() {
- return new OldNotifProviderConfig(this);
+ public NotificationProviderConfig build() {
+ return new NotificationProviderConfig(this);
}
}
}
/**
* Package for all internal helper classes.
*/
-package org.opendaylight.openflowplugin.applications.old.notification.supplier.tools;
\ No newline at end of file
+package org.opendaylight.openflowplugin.applications.notification.supplier.tools;
\ No newline at end of file
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.notification.supplier.rev150820;
+public class NotifModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.notification.supplier.rev150820.AbstractNotifModule {
+ public NotifModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public NotifModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.notification.supplier.rev150820.NotifModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ // TODO:implement
+ throw new java.lang.UnsupportedOperationException();
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: notification-supplier yang module local name: notification-supplier
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Sun May 22 10:45:47 IST 2016
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.notification.supplier.rev150820;
+public class NotifModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.notification.supplier.rev150820.AbstractNotifModuleFactory {
+
+}
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:applications:old-notification-supplier">prefix:old-notification-supplier</type>
- <name>old-notification-supplier</name>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:applications:notification-supplier">prefix:notification-supplier</type>
+ <name>notification-supplier</name>
<data-broker>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
<name>binding-data-broker</name>
<name>binding-notification-broker</name>
</notification-service>
- <old-notification-supplier-settings>
+ <notification-supplier-settings>
<!--<port-support>true</port-support>-->
<!--<flow-support>true</flow-support>-->
<meter-support>true</meter-support>
<meter-stat-support>false</meter-stat-support>
<queue-stat-support>false</queue-stat-support>
<flow-stat-support>false</flow-stat-support>
- </old-notification-supplier-settings>
+ </notification-supplier-settings>
</module>
</configuration>
<required-capabilities>
- <capability>urn:opendaylight:params:xml:ns:yang:openflow:applications:old-notification-supplier?module=old-notification-supplier&revision=2015-08-20</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:openflow:applications:notification-supplier?module=notification-supplier&revision=2015-08-20</capability>
<capability>urn:opendaylight:flow:inventory?module=flow-node-inventory&revision=2013-08-19</capability>
<capability>urn:opendaylight:inventory?module=opendaylight-inventory&revision=2013-08-19</capability>
<capability>urn:opendaylight:flow:types?module=opendaylight-flow-types&revision=2013-10-26</capability>
-module old-notification-supplier {
+module notification-supplier {
yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:openflow:applications:old-notification-supplier";
- prefix "old-notif";
+ namespace "urn:opendaylight:params:xml:ns:yang:openflow:applications:notification-supplier";
+ prefix "notification";
import config {prefix config; revision-date 2013-04-05;}
import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28;}
description
- "Translator tool for relevant wildcard path DataChangeEvent to Old Notifications.";
+ "Translator tool for relevant wildcard path DataChangeEvent to Notifications.";
revision "2015-08-20" {
description
"Initial revision";
}
- identity old-notification-supplier {
+ identity notification-supplier {
base "config:module-type";
- config:java-name-prefix OldNotif;
+ config:java-name-prefix Notif;
}
augment "/config:modules/config:module/config:configuration" {
- case old-notification-supplier {
- when "/config:modules/config:module/config:type = 'old-notification-supplier'";
+ case notification-supplier {
+ when "/config:modules/config:module/config:type = 'notification-supplier'";
container notification-service {
uses config:service-ref {
}
}
- container old-notification-supplier-settings {
+ container notification-supplier-settings {
leaf flow-support {
type boolean;
default true;
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.tools.NotificationProviderConfig;
+import org.opendaylight.openflowplugin.applications.notification.supplier.tools.NotificationProviderConfig.NotificationProviderConfigBuilder;
+
+public class NotificationProviderImplTest {
+
+ private NotificationProviderService notificationProviderService;
+ private NotificationProviderConfig config;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initialization() {
+ dataBroker = mock(DataBroker.class);
+ notificationProviderService = mock(NotificationProviderService.class);
+ }
+
+ @Test
+ public void testCreateAllSuppliers() {
+ final NotificationProviderConfig config = createAllConfigSupplier();
+ final NotificationProviderImpl provider = new NotificationProviderImpl(config, notificationProviderService, dataBroker);
+ provider.start();
+ final List<NotificationSupplierDefinition<?>> listSuppliers = provider.getSupplierList();
+ int nrOfSuppliers = 0;
+ for (final NotificationSupplierDefinition<?> supplier : listSuppliers) {
+ if (supplier != null) {
+ nrOfSuppliers++;
+ }
+ }
+ assertEquals(11, nrOfSuppliers);
+ }
+
+ @Test
+ public void testCreateRootSuppliersOnly() {
+ final NotificationProviderConfig config = createNonConfigSupplier();
+ final NotificationProviderImpl provider = new NotificationProviderImpl(config, notificationProviderService, dataBroker);
+ provider.start();
+ final List<NotificationSupplierDefinition<?>> listSuppliers = provider.getSupplierList();
+ int nrOfSuppliers = 0;
+ for (final NotificationSupplierDefinition<?> supplier : listSuppliers) {
+ if (supplier != null) {
+ nrOfSuppliers++;
+ }
+ }
+ assertEquals(2, nrOfSuppliers);
+ }
+
+ private NotificationProviderConfig createAllConfigSupplier() {
+ final NotificationProviderConfigBuilder builder = new NotificationProviderConfigBuilder();
+ builder.setFlowStatSupport(true);
+ builder.setFlowSupport(true);
+ builder.setFlowTableStatSupport(true);
+ builder.setGroupStatSupport(true);
+ builder.setGroupSupport(true);
+ builder.setMeterStatSupport(true);
+ builder.setMeterSupport(true);
+ builder.setNodeConnectorStatSupport(true);
+ builder.setQueueStatSupport(true);
+ return builder.build();
+ }
+
+ private NotificationProviderConfig createNonConfigSupplier() {
+ final NotificationProviderConfigBuilder builder = new NotificationProviderConfigBuilder();
+ builder.setFlowStatSupport(false);
+ builder.setFlowSupport(false);
+ builder.setFlowTableStatSupport(false);
+ builder.setGroupStatSupport(false);
+ builder.setGroupSupport(false);
+ builder.setMeterStatSupport(false);
+ builder.setMeterSupport(false);
+ builder.setNodeConnectorStatSupport(false);
+ builder.setQueueStatSupport(false);
+ return builder.build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ */
+public class NodeConnectorNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final String FLOW_CODE_CONNECTOR_ID = "test-con-111";
+ private NodeConnectorNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new NodeConnectorNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final NodeConnectorUpdated notification = notifSupplierImpl.createNotification(createTestFlowCapableNodeConnecor(),
+ createTestFlowCapableConnectorNodePath());
+ assertNotNull(notification);
+ assertEquals(FLOW_CODE_CONNECTOR_ID, notification.getId().getValue());
+ assertEquals(FLOW_CODE_CONNECTOR_ID, notification.getNodeConnectorRef().getValue()
+ .firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue());
+ assertEquals(FLOW_NODE_ID, notification.getNodeConnectorRef().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestFlowCapableConnectorNodePath(), createTestFlowCapableNodeConnecor());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(NodeConnectorUpdated.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestFlowCapableConnectorNodePath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestFlowCapableNodeConnecor(), null);
+ }
+
+ @Test
+ public void testDelete() {
+ final NodeConnectorRemoved notification = notifSupplierImpl.deleteNotification(createTestFlowCapableConnectorNodePath());
+ assertNotNull(notification);
+ assertEquals(FLOW_CODE_CONNECTOR_ID, notification.getNodeConnectorRef().getValue()
+ .firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue());
+ assertEquals(FLOW_NODE_ID, notification.getNodeConnectorRef().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testDeleteChangeEvent() {
+ final Set<InstanceIdentifier<?>> removeData = new HashSet<>();
+ removeData.add(createTestFlowCapableConnectorNodePath());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(null, null, removeData));
+ verify(notifProviderService, times(1)).publish(Matchers.any(NodeConnectorRemoved.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDeleteFromNullPath() {
+ notifSupplierImpl.deleteNotification(null);
+ }
+
+ private static InstanceIdentifier<FlowCapableNodeConnector> createTestFlowCapableConnectorNodePath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(FLOW_CODE_CONNECTOR_ID))).augmentation(FlowCapableNodeConnector.class);
+ }
+
+ private static FlowCapableNodeConnector createTestFlowCapableNodeConnecor() {
+ final FlowCapableNodeConnectorBuilder builder = new FlowCapableNodeConnectorBuilder();
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ */
+public class NodeNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private NodeNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new NodeNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final NodeUpdated notification = notifSupplierImpl.createNotification(createTestFlowCapableNode(),
+ createTestFlowCapableNodePath());
+ assertNotNull(notification);
+ assertEquals(FLOW_NODE_ID, notification.getId().getValue());
+ assertEquals(FLOW_NODE_ID, notification.getNodeRef().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestFlowCapableNodePath(), createTestFlowCapableNode());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(NodeUpdated.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNode() {
+ notifSupplierImpl.createNotification(null, createTestFlowCapableNodePath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestFlowCapableNode(), null);
+ }
+
+ @Test
+ public void testDelete() {
+ final NodeRemoved notification = notifSupplierImpl.deleteNotification(createTestFlowCapableNodePath());
+ assertNotNull(notification);
+ assertEquals(FLOW_NODE_ID, notification.getNodeRef().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testDeleteChangeEvent() {
+ final Set<InstanceIdentifier<?>> removeData = new HashSet<>();
+ removeData.add(createTestFlowCapableNodePath());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(null, null, removeData));
+ verify(notifProviderService, times(1)).publish(Matchers.any(NodeRemoved.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDeleteFromNullPath() {
+ notifSupplierImpl.deleteNotification(null);
+ }
+
+ private static InstanceIdentifier<FlowCapableNode> createTestFlowCapableNodePath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .augmentation(FlowCapableNode.class);
+ }
+
+ private static FlowCapableNode createTestFlowCapableNode() {
+ final FlowCapableNodeBuilder builder = new FlowCapableNodeBuilder();
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.helper;
+
+import static org.mockito.Mockito.mock;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ */
+public class TestChangeEventBuildHelper {
+
+ private TestChangeEventBuildHelper() {
+ throw new UnsupportedOperationException("Test utility class");
+ }
+
+ public static AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> createTestDataEvent(
+ final Map<InstanceIdentifier<?>, DataObject> createdData,
+ final Map<InstanceIdentifier<?>, DataObject> updatedData,
+ final Set<InstanceIdentifier<?>> removedData) {
+ return new AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>() {
+
+ @Override
+ public DataObject getUpdatedSubtree() {
+ return mock(DataObject.class);
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+ if (updatedData != null) {
+ return Collections.unmodifiableMap(updatedData);
+ } else {
+ return Collections.emptyMap();
+ }
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedPaths() {
+ if (removedData != null) {
+ return Collections.unmodifiableSet(removedData);
+ } else {
+ return Collections.emptySet();
+ }
+ }
+
+ @Override
+ public DataObject getOriginalSubtree() {
+ return mock(DataObject.class);
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+ if (createdData != null) {
+ return Collections.unmodifiableMap(createdData);
+ } else {
+ return Collections.emptyMap();
+ }
+ }
+ };
+ }
+
+ public static AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> createEmptyTestDataEvent() {
+ return new AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>() {
+
+ @Override
+ public DataObject getUpdatedSubtree() {
+ return mock(DataObject.class);
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedPaths() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public DataObject getOriginalSubtree() {
+ return mock(DataObject.class);
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+ return Collections.emptyMap();
+ }
+ };
+ }
+
+ public static AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> createNullTestDataEvent() {
+ return new AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>() {
+
+ @Override
+ public DataObject getUpdatedSubtree() {
+ return null;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+ return null;
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedPaths() {
+ return null;
+ }
+
+ @Override
+ public DataObject getOriginalSubtree() {
+ return null;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
+ return null;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+ return null;
+ }
+ };
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.helper;
+
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Created by mirehak on 9/2/15.
+ */
+public class TestSupplierVerifyHelper {
+
+ private TestSupplierVerifyHelper() {
+ throw new UnsupportedOperationException("Test utility class");
+ }
+
+ /**
+ * check if wildcarded path is not null
+ *
+ * @param dataBroker
+ */
+ public static void verifyDataChangeRegistration(DataBroker dataBroker) {
+ Mockito.verify(dataBroker).registerDataChangeListener(
+ Matchers.eq(LogicalDatastoreType.OPERATIONAL),
+ Matchers.notNull(InstanceIdentifier.class),
+ Matchers.notNull(DataChangeListener.class),
+ Matchers.eq(AsyncDataBroker.DataChangeScope.BASE));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.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.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ */
+public class FlowNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final Short FLOW_TABLE_ID = 111;
+ private static final String FLOW_ID = "test-flow-111";
+ private FlowNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new FlowNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final FlowAdded notification = notifSupplierImpl.createNotification(createTestFlow(), createTestFlowPath());
+ assertNotNull(notification);
+ assertEquals(FLOW_ID, notification.getFlowRef().getValue().firstKeyOf(Flow.class, FlowKey.class).getId().getValue());
+ assertEquals(FLOW_TABLE_ID, notification.getFlowRef().getValue().firstKeyOf(Table.class, TableKey.class).getId());
+ assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestFlowPath(), createTestFlow());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(FlowAdded.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestFlowPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestFlow(), null);
+ }
+
+ @Test
+ public void testUpdate() {
+ final FlowUpdated notification = notifSupplierImpl.updateNotification(createTestFlow(), createTestFlowPath());
+ assertNotNull(notification);
+ assertEquals(FLOW_ID, notification.getFlowRef().getValue().firstKeyOf(Flow.class, FlowKey.class).getId().getValue());
+ assertEquals(FLOW_TABLE_ID, notification.getFlowRef().getValue().firstKeyOf(Table.class, TableKey.class).getId());
+ assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testUpdateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestFlowPath(), createTestFlow());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(FlowUpdated.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestFlowPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestFlow(), null);
+ }
+
+ @Test
+ public void testDelete() {
+ final FlowRemoved notification = notifSupplierImpl.deleteNotification(createTestFlowPath());
+ assertNotNull(notification);
+ assertEquals(FLOW_ID, notification.getFlowRef().getValue().firstKeyOf(Flow.class, FlowKey.class).getId().getValue());
+ assertEquals(FLOW_TABLE_ID, notification.getFlowRef().getValue().firstKeyOf(Table.class, TableKey.class).getId());
+ assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testDeleteChangeEvent() {
+ final Set<InstanceIdentifier<?>> removeData = new HashSet<>();
+ removeData.add(createTestFlowPath());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(null, null, removeData));
+ verify(notifProviderService, times(1)).publish(Matchers.any(FlowRemoved.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDeleteFromNullPath() {
+ notifSupplierImpl.deleteNotification(null);
+ }
+
+ private static InstanceIdentifier<Flow> createTestFlowPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(FLOW_TABLE_ID))
+ .child(Flow.class, new FlowKey(new FlowId(FLOW_ID)));
+ }
+
+ private static Flow createTestFlow() {
+ final FlowBuilder builder = new FlowBuilder();
+ builder.setId(new FlowId(FLOW_ID));
+ builder.setTableId(FLOW_TABLE_ID);
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ */
+public class GroupNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final Long GROUP_ID = 111L;
+ private GroupNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new GroupNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final GroupAdded notification = notifSupplierImpl.createNotification(createTestGroup(), createTestGroupPath());
+ assertNotNull(notification);
+ assertEquals(GROUP_ID, notification.getGroupId().getValue());
+ assertEquals(GROUP_ID, notification.getGroupRef().getValue().firstKeyOf(Group.class, GroupKey.class).getGroupId().getValue());
+ assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestGroupPath(), createTestGroup());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(GroupAdded.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestGroupPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestGroup(), null);
+ }
+
+ @Test
+ public void testUpdate() {
+ final GroupUpdated notification = notifSupplierImpl.updateNotification(createTestGroup(), createTestGroupPath());
+ assertNotNull(notification);
+ assertEquals(GROUP_ID, notification.getGroupId().getValue());
+ assertEquals(GROUP_ID, notification.getGroupRef().getValue().firstKeyOf(Group.class, GroupKey.class).getGroupId().getValue());
+ assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testUpdateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestGroupPath(), createTestGroup());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(GroupUpdated.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestGroupPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestGroup(), null);
+ }
+
+ @Test
+ public void testDelete() {
+ final GroupRemoved notification = notifSupplierImpl.deleteNotification(createTestGroupPath());
+ assertNotNull(notification);
+ assertEquals(GROUP_ID, notification.getGroupId().getValue());
+ assertEquals(GROUP_ID, notification.getGroupRef().getValue().firstKeyOf(Group.class, GroupKey.class).getGroupId().getValue());
+ assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testDeleteChangeEvent() {
+ final Set<InstanceIdentifier<?>> removeData = new HashSet<>();
+ removeData.add(createTestGroupPath());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(null, null, removeData));
+ verify(notifProviderService, times(1)).publish(Matchers.any(GroupRemoved.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDeleteFromNullPath() {
+ notifSupplierImpl.deleteNotification(null);
+ }
+
+ private static InstanceIdentifier<Group> createTestGroupPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(GROUP_ID)));
+ }
+
+ private static Group createTestGroup() {
+ final GroupBuilder builder = new GroupBuilder();
+ builder.setGroupId(new GroupId(GROUP_ID));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ */
+public class MeterNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final Long METER_ID = 111L;
+ private MeterNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new MeterNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final MeterAdded notification = notifSupplierImpl.createNotification(createTestMeter(), createTestMeterPath());
+ assertNotNull(notification);
+ assertEquals(METER_ID, notification.getMeterId().getValue());
+ assertEquals(METER_ID, notification.getMeterRef().getValue().firstKeyOf(Meter.class, MeterKey.class).getMeterId().getValue());
+ assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestMeterPath(), createTestMeter());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(MeterAdded.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestMeterPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestMeter(), null);
+ }
+
+ @Test
+ public void testUpdate() {
+ final MeterUpdated notification = notifSupplierImpl
+ .updateNotification(createTestMeter(), createTestMeterPath());
+ assertNotNull(notification);
+ assertEquals(METER_ID, notification.getMeterId().getValue());
+ assertEquals(METER_ID, notification.getMeterRef().getValue().firstKeyOf(Meter.class, MeterKey.class).getMeterId().getValue());
+ assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testUdateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestMeterPath(), createTestMeter());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(MeterUpdated.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestMeterPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestMeter(), null);
+ }
+
+ @Test
+ public void testDelete() {
+ final MeterRemoved notification = notifSupplierImpl.deleteNotification(createTestMeterPath());
+ assertNotNull(notification);
+ assertEquals(METER_ID, notification.getMeterId().getValue());
+ assertEquals(METER_ID, notification.getMeterRef().getValue().firstKeyOf(Meter.class, MeterKey.class).getMeterId().getValue());
+ assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ }
+
+ @Test
+ public void testDeleteChangeEvent() {
+ final Set<InstanceIdentifier<?>> removeData = new HashSet<>();
+ removeData.add(createTestMeterPath());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(null, null, removeData));
+ verify(notifProviderService, times(1)).publish(Matchers.any(MeterRemoved.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDeleteFromNullPath() {
+ notifSupplierImpl.deleteNotification(null);
+ }
+
+ private static InstanceIdentifier<Meter> createTestMeterPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .augmentation(FlowCapableNode.class).child(Meter.class, new MeterKey(new MeterId(METER_ID)));
+ }
+
+ private static Meter createTestMeter() {
+ final MeterBuilder builder = new MeterBuilder();
+ builder.setMeterId(new MeterId(METER_ID));
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FlowStatNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final Short FLOW_TABLE_ID = 111;
+ private static final String FLOW_ID = "test-flow-111";
+ private FlowStatNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new FlowStatNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final FlowsStatisticsUpdate notification = notifSupplierImpl.createNotification(createTestFlowStat(), createTestFlowStatPath());
+ assertNotNull(notification);
+ assertEquals(FLOW_NODE_ID, notification.getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestFlowStatPath(), createTestFlowStat());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(FlowsStatisticsUpdate.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestFlowStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestFlowStat(), null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestFlowStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestFlowStat(), null);
+ }
+
+ private static InstanceIdentifier<FlowStatistics> createTestFlowStatPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(FLOW_TABLE_ID))
+ .child(Flow.class, new FlowKey(new FlowId(FLOW_ID))).augmentation(FlowStatisticsData.class)
+ .child(FlowStatistics.class);
+ }
+
+ private static FlowStatistics createTestFlowStat() {
+ final FlowStatisticsBuilder builder = new FlowStatisticsBuilder();
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FlowTableStatNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final Short FLOW_TABLE_ID = 111;
+ private static final String FLOW_ID = "test-flow-111";
+ private FlowTableStatNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new FlowTableStatNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final FlowTableStatisticsUpdate notification = notifSupplierImpl.createNotification(createTestFlowTableStat(),
+ createTestFlowTableStatPath());
+ assertNotNull(notification);
+ assertEquals(FLOW_NODE_ID, notification.getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestFlowTableStatPath(), createTestFlowTableStat());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(FlowTableStatisticsUpdate.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestFlowTableStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestFlowTableStat(), null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestFlowTableStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestFlowTableStat(), null);
+ }
+
+ private static InstanceIdentifier<FlowTableStatistics> createTestFlowTableStatPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(FLOW_TABLE_ID))
+ .augmentation(FlowTableStatisticsData.class).child(FlowTableStatistics.class);
+ }
+
+ private static FlowTableStatistics createTestFlowTableStat() {
+ final FlowTableStatisticsBuilder builder = new FlowTableStatisticsBuilder();
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class GroupStatNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final Long FLOW_TABLE_ID = 111L;
+ private GroupStatNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new GroupStatNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final GroupStatisticsUpdated notification = notifSupplierImpl.createNotification(createTestGroupStat(),
+ createTestGroupStatPath());
+ assertNotNull(notification);
+ assertEquals(FLOW_NODE_ID, notification.getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestGroupStatPath(), createTestGroupStat());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(GroupStatisticsUpdated.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestGroupStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestGroupStat(), null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestGroupStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestGroupStat(), null);
+ }
+
+ private static InstanceIdentifier<GroupStatistics> createTestGroupStatPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(FLOW_TABLE_ID)))
+ .augmentation(NodeGroupStatistics.class).child(GroupStatistics.class);
+ }
+
+ private static GroupStatistics createTestGroupStat() {
+ final GroupStatisticsBuilder builder = new GroupStatisticsBuilder();
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MeterStatNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final Long FLOW_METER_ID = 111L;
+ private MeterStatNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new MeterStatNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final MeterStatisticsUpdated notification = notifSupplierImpl.createNotification(createTestMeterStat(),
+ createTestMeterStatPath());
+ assertNotNull(notification);
+ assertEquals(FLOW_NODE_ID, notification.getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestMeterStatPath(), createTestMeterStat());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(MeterStatisticsUpdated.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestMeterStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestMeterStat(), null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestMeterStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestMeterStat(), null);
+ }
+
+ private static InstanceIdentifier<MeterStatistics> createTestMeterStatPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .augmentation(FlowCapableNode.class).child(Meter.class, new MeterKey(new MeterId(FLOW_METER_ID)))
+ .augmentation(NodeMeterStatistics.class).child(MeterStatistics.class);
+ }
+
+ private static MeterStatistics createTestMeterStat() {
+ final MeterStatisticsBuilder builder = new MeterStatisticsBuilder();
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.flow.capable.node.connector.statistics.FlowCapableNodeConnectorStatisticsBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NodeConnectorStatNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final String FLOW_CODE_CONNECTOR_ID = "test-con-111";
+ private NodeConnectorStatNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new NodeConnectorStatNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final NodeConnectorStatisticsUpdate notification = notifSupplierImpl.createNotification(createTestConnectorStat(),
+ createTestConnectorStatPath());
+ assertNotNull(notification);
+ assertEquals(FLOW_NODE_ID, notification.getId().getValue());
+ assertEquals(FLOW_CODE_CONNECTOR_ID, notification.getNodeConnector().get(0).getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestConnectorStatPath(), createTestConnectorStat());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(NodeConnectorStatisticsUpdate.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestConnectorStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestConnectorStat(), null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestConnectorStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestConnectorStat(), null);
+ }
+
+ private static InstanceIdentifier<FlowCapableNodeConnectorStatistics> createTestConnectorStatPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(FLOW_CODE_CONNECTOR_ID)))
+ .augmentation(FlowCapableNodeConnectorStatisticsData.class)
+ .child(FlowCapableNodeConnectorStatistics.class);
+ }
+
+ private static FlowCapableNodeConnectorStatistics createTestConnectorStat() {
+ final FlowCapableNodeConnectorStatisticsBuilder builder = new FlowCapableNodeConnectorStatisticsBuilder();
+ return builder.build();
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.applications.notification.supplier.impl.item.stat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.queues.Queue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.FlowCapableNodeConnectorQueueStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.QueueStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.flow.capable.node.connector.queue.statistics.FlowCapableNodeConnectorQueueStatisticsBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ */
+public class QueueStatNotificationSupplierImplTest {
+
+ private static final String FLOW_NODE_ID = "test-111";
+ private static final String FLOW_CODE_CONNECTOR_ID = "test-con-111";
+ private QueueStatNotificationSupplierImpl notifSupplierImpl;
+ private NotificationProviderService notifProviderService;
+ private DataBroker dataBroker;
+
+ @Before
+ public void initalization() {
+ notifProviderService = mock(NotificationProviderService.class);
+ dataBroker = mock(DataBroker.class);
+ notifSupplierImpl = new QueueStatNotificationSupplierImpl(notifProviderService, dataBroker);
+ TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNullChangeEvent() {
+ notifSupplierImpl.onDataChanged(null);
+ }
+
+ @Test
+ public void testNullableChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testEmptyChangeEvent() {
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+ }
+
+ @Test
+ public void testCreate() {
+ final QueueStatisticsUpdate notification = notifSupplierImpl.createNotification(createTestQueueStat(),
+ createTestQueueStatPath());
+ assertNotNull(notification);
+ assertEquals(FLOW_NODE_ID, notification.getId().getValue());
+ assertEquals(FLOW_CODE_CONNECTOR_ID, notification.getNodeConnector().get(0).getId().getValue());
+ }
+
+ @Test
+ public void testCreateChangeEvent() {
+ final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+ createdData.put(createTestQueueStatPath(), createTestQueueStat());
+ notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+ verify(notifProviderService, times(1)).publish(Matchers.any(QueueStatisticsUpdate.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestQueueStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestQueueStat(), null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullNodeConnector() {
+ notifSupplierImpl.createNotification(null, createTestQueueStatPath());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateFromNullPath() {
+ notifSupplierImpl.createNotification(createTestQueueStat(), null);
+ }
+
+ private static InstanceIdentifier<FlowCapableNodeConnectorQueueStatisticsData> createTestQueueStatPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+ .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(FLOW_CODE_CONNECTOR_ID)))
+ .augmentation(FlowCapableNodeConnector.class).child(Queue.class)
+ .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class);
+ }
+
+ private static FlowCapableNodeConnectorQueueStatisticsData createTestQueueStat() {
+ final FlowCapableNodeConnectorQueueStatisticsDataBuilder builder = new FlowCapableNodeConnectorQueueStatisticsDataBuilder();
+ final FlowCapableNodeConnectorQueueStatisticsBuilder value = new FlowCapableNodeConnectorQueueStatisticsBuilder();
+ builder.setFlowCapableNodeConnectorQueueStatistics(value.build());
+ return builder.build();
+ }
+}
+
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
</plugin>
-
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-artifacts</id>
- <goals>
- <goal>attach-artifact</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <artifacts>
- <artifact>
- <file>${project.build.directory}/classes/initial/70-of-switch-config-pusher.xml</file>
- <type>xml</type>
- <classifier>config</classifier>
- </artifact>
- </artifacts>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
</project>
package org.opendaylight.openflowplugin.openflow.ofswitch.config;
import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.NodeConfigService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.SetConfigInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.SwitchConfigFlag;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
*/
public class DefaultConfigPusher implements AutoCloseable, DataChangeListener {
- private NodeConfigService nodeConfigService;
+ private final NodeConfigService nodeConfigService;
+ private final DataBroker dataBroker;
+ private ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
- public DefaultConfigPusher(NodeConfigService nodeConfigService) {
+ public DefaultConfigPusher(NodeConfigService nodeConfigService, DataBroker dataBroker) {
this.nodeConfigService = nodeConfigService;
+ this.dataBroker = dataBroker;
}
- @Override
- public void close() throws Exception {
+ public void start() {
+ InstanceIdentifier<FlowCapableNode> path = InstanceIdentifier.create(Nodes.class).child(Node.class).
+ augmentation(FlowCapableNode.class);
+ dataChangeListenerRegistration = dataBroker.registerDataChangeListener(
+ LogicalDatastoreType.OPERATIONAL,
+ path, this, AsyncDataBroker.DataChangeScope.BASE);
+ }
+ @Override
+ public void close() {
+ if(dataChangeListenerRegistration != null) {
+ dataChangeListenerRegistration.close();
+ }
}
@Override
+++ /dev/null
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.of._switch.config.pusher.rev141015;
-
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.openflowplugin.openflow.ofswitch.config.DefaultConfigPusher;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.NodeConfigService;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class DefaultConfigPusherModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.of._switch.config.pusher.rev141015.AbstractDefaultConfigPusherModule {
- public DefaultConfigPusherModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public DefaultConfigPusherModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.of._switch.config.pusher.rev141015.DefaultConfigPusherModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- InstanceIdentifier<FlowCapableNode> path = InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
- NodeConfigService nodeConfigService = getRpcRegistryDependency().getRpcService(NodeConfigService.class);
- return getDataBrokerDependency().registerDataChangeListener(
- LogicalDatastoreType.OPERATIONAL,
- path,
- new DefaultConfigPusher(nodeConfigService),
- AsyncDataBroker.DataChangeScope.BASE);
- }
-
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: of-switch-config-pusher yang module local name: of-switch-config-pusher
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Wed Oct 15 10:43:24 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.of._switch.config.pusher.rev141015;
-public class DefaultConfigPusherModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.of._switch.config.pusher.rev141015.AbstractDefaultConfigPusherModuleFactory {
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2014 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
- -->
-
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-
-<snapshot>
- <configuration>
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:applications:of-switch-config-pusher">prefix:of-switch-config-pusher</type>
- <name>of-switch-config-pusher</name>
- <data-broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
- <name>binding-data-broker</name>
- </data-broker>
- <rpc-registry>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
- <name>binding-rpc-broker</name>
- </rpc-registry>
- </module>
-
- </modules>
- </data>
- </configuration>
-</snapshot>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
+
+ <odl:rpc-service id="nodeConfigService" interface="org.opendaylight.yang.gen.v1.urn.opendaylight.module.config.rev141015.NodeConfigService"/>
+
+ <bean id="LLDPPacketPuntEnforcer" class="org.opendaylight.openflowplugin.openflow.ofswitch.config.DefaultConfigPusher"
+ init-method="start" destroy-method="close">
+ <argument ref="nodeConfigService"/>
+ <argument ref="dataBroker"/>
+ </bean>
+</blueprint>
\ No newline at end of file
+++ /dev/null
-module of-switch-config-pusher {
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:openflow:applications:of-switch-config-pusher";
- prefix "of-switch-config-pusher";
- import config {prefix config; revision-date 2013-04-05;}
- import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
-
- description
- "of-switch-config-pusher-custom-config-impl";
-
- revision "2014-10-15" {
- description
- "Initial revision";
- }
-
- identity of-switch-config-pusher {
- base "config:module-type";
- config:java-name-prefix DefaultConfigPusher;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case of-switch-config-pusher {
- when "/config:modules/config:module/config:type = 'of-switch-config-pusher'";
- container rpc-registry {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity mdsal:binding-rpc-registry;
- }
- }
- }
- container data-broker {
- uses config:service-ref {
- refine type {
- mandatory false;
- config:required-identity mdsal:binding-async-data-broker;
- }
- }
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2015 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.old.notification.supplier.rev150820;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.config.api.DependencyResolver;
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.openflowplugin.applications.old.notification.supplier.tools.OldNotifProviderConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Generated module introducer for OldNotificationSupplier Module class.
- */
-public class OldNotifModule extends AbstractOldNotifModule {
-
- static final Logger LOG = LoggerFactory.getLogger(OldNotifModule.class);
-
- private static final String LOAD_SETTINGS_XML_FAIL = "Load the xml ConfigSubsystem input value fail!";
- private static final boolean DEFAULT_ITEM_NOTIF_ALLOWED = true;
- private static final boolean DEFAULT_STAT_NOTIF_ALLOWED = false;
-
- /**
- * Module constructor
- *
- * @param identifier - {@link ModuleIdentifier}
- * @param dependencyResolver - {@link DependencyResolver}
- */
- public OldNotifModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- /**
- * Module constructor
- *
- * @param identifier - {@link ModuleIdentifier}
- * @param dependencyResolver - {@link DependencyResolver}
- * @param oldModule - {@link OldNotifModule}
- * @param oldInstance - {@link AutoCloseable}
- */
- public OldNotifModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver,
- final OldNotifModule oldModule, final AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- LOG.info("OldNotificationSupplier module initialization.");
- LOG.warn("OldNotificationSupplier module is marked like DEPRECATED. Modul could supplie old notification only for lithium release.");
- final OldNotifProviderConfig config = createConfig();
- return null;
- }
-
- /*
- * Help method for populating all ConfigSubsystem values to OldNotifProviderConfig immutable value holder.
- */
- private OldNotifProviderConfig createConfig() {
- final OldNotificationSupplierSettings settings = Preconditions.checkNotNull(getOldNotificationSupplierSettings());
- final OldNotifProviderConfig.OldNotifProviderConfigBuilder builder = OldNotifProviderConfig.builder();
- if (settings.getFlowSupport() != null) {
- builder.setFlowSupport(settings.getFlowSupport());
- } else {
- LOG.warn(LOAD_SETTINGS_XML_FAIL + " FlowSupport value is set to {} ", DEFAULT_ITEM_NOTIF_ALLOWED);
- builder.setFlowSupport(DEFAULT_ITEM_NOTIF_ALLOWED);
- }
-
- if (settings.getMeterSupport() != null) {
- builder.setMeterSupport(settings.getMeterSupport());
- } else {
- LOG.warn(LOAD_SETTINGS_XML_FAIL + " MeterSupport value is set to {} ", DEFAULT_ITEM_NOTIF_ALLOWED);
- builder.setMeterSupport(DEFAULT_ITEM_NOTIF_ALLOWED);
- }
- if (settings.getGroupSupport() != null) {
- builder.setGroupSupport(settings.getGroupSupport());
- } else {
- LOG.warn(LOAD_SETTINGS_XML_FAIL + " GroupSupport value is set to {} ", DEFAULT_ITEM_NOTIF_ALLOWED);
- builder.setGroupSupport(DEFAULT_ITEM_NOTIF_ALLOWED);
- }
- if (settings.getNodeConnectorStatSupport() != null) {
- builder.setNodeConnectorStatSupport(settings.getNodeConnectorStatSupport());
- } else {
- LOG.warn(LOAD_SETTINGS_XML_FAIL + " NodeConnectorStatSupport value is set to {} ", DEFAULT_STAT_NOTIF_ALLOWED);
- builder.setNodeConnectorStatSupport(DEFAULT_STAT_NOTIF_ALLOWED);
- }
- if (settings.getFlowTableStatSupport() != null) {
- builder.setFlowTableStatSupport(settings.getFlowTableStatSupport());
- } else {
- LOG.warn(LOAD_SETTINGS_XML_FAIL + " FlowTableStatSupport value is set to {} ", DEFAULT_STAT_NOTIF_ALLOWED);
- builder.setFlowTableStatSupport(DEFAULT_STAT_NOTIF_ALLOWED);
- }
- if (settings.getGroupStatSupport() != null) {
- builder.setGroupStatSupport(settings.getGroupStatSupport());
- } else {
- LOG.warn(LOAD_SETTINGS_XML_FAIL + " GroupStatSupport value is set to {} ", DEFAULT_STAT_NOTIF_ALLOWED);
- builder.setGroupStatSupport(DEFAULT_STAT_NOTIF_ALLOWED);
- }
- if (settings.getMeterStatSupport() != null) {
- builder.setMeterStatSupport(settings.getMeterStatSupport());
- } else {
- LOG.warn(LOAD_SETTINGS_XML_FAIL + " MeterStatSupport value is set to {} ", DEFAULT_STAT_NOTIF_ALLOWED);
- builder.setMeterStatSupport(DEFAULT_STAT_NOTIF_ALLOWED);
- }
- if (settings.getQueueStatSupport() != null) {
- builder.setQueueStatSupport(settings.getQueueStatSupport());
- } else {
- LOG.warn(LOAD_SETTINGS_XML_FAIL + " QueueStatSupport value is set to {} ", DEFAULT_STAT_NOTIF_ALLOWED);
- builder.setQueueStatSupport(DEFAULT_STAT_NOTIF_ALLOWED);
- }
- if (settings.getFlowStatSupport() != null) {
- builder.setFlowStatSupport(settings.getFlowStatSupport());
- } else {
- LOG.warn(LOAD_SETTINGS_XML_FAIL + " QueueStatSupport value is set to {} ", DEFAULT_STAT_NOTIF_ALLOWED);
- builder.setFlowStatSupport(DEFAULT_STAT_NOTIF_ALLOWED);
- }
- return builder.build();
- }
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: old-notification-supplier yang module local name: old-notification-supplier
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Fri Aug 21 00:31:49 CEST 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.old.notification.supplier.rev150820;
-
-public class OldNotifModuleFactory
- extends
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.old.notification.supplier.rev150820.AbstractOldNotifModuleFactory {
-
-}
<module>of-switch-config-pusher</module>
<module>lldp-speaker</module>
<!-- deprecated apps -->
- <module>old-notification-supplier</module>
+ <module>notification-supplier</module>
<!-- nsf apps -->
<module>inventory-manager</module>
<module>statistics-manager</module>
- <module>statistics-manager-config</module>
<module>topology-manager</module>
<module>forwardingrules-manager</module>
- <module>forwardingrules-manager-config</module>
+ <module>forwardingrules-sync</module>
<module>topology-lldp-discovery</module>
<!--<module>features</module>-->
<!-- experimental apps -->
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (c) 2014 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
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>applications</artifactId>
- <version>0.3.0-SNAPSHOT</version>
- </parent>
-
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>statistics-manager-config</artifactId>
- <description>Configuration files for statistics manager</description>
- <packaging>jar</packaging>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-artifacts</id>
- <goals>
- <goal>attach-artifact</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <artifacts>
- <artifact>
- <file>${project.build.directory}/classes/initial/30-statistics-manager.xml</file>
- <type>xml</type>
- <classifier>config</classifier>
- </artifact>
- </artifacts>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-
-
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/openflowplugin.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/openflowplugin.git</developerConnection>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_OpenFlow_Plugin:Main</url>
- <tag>HEAD</tag>
- </scm>
-
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
- Copyright (c) 2014 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
--->
-<snapshot>
- <configuration>
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:statsmanager="urn:opendaylight:params:xml:ns:yang:openflowplugin:app:statistics-manager">
- statsmanager:statistics-manager
- </type>
- <name>statistics-manager</name>
-
- <rpc-registry>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
- <name>binding-rpc-broker</name>
- </rpc-registry>
-
- <data-broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
- <name>binding-data-broker</name>
- </data-broker>
-
- <notification-service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
- binding:binding-notification-service
- </type>
- <name>binding-notification-broker</name>
- </notification-service>
-
- <ownership-service>
- <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
- <name>entity-ownership-service</name>
- </ownership-service>
-
- <statistics-manager-settings>
- <min-request-net-monitor-interval>3000</min-request-net-monitor-interval>
- <max-nodes-for-collector>16</max-nodes-for-collector>
- </statistics-manager-settings>
-
- </module>
- </modules>
- </data>
- </configuration>
-
- <required-capabilities>
- <capability>urn:opendaylight:params:xml:ns:yang:openflowplugin:app:statistics-manager?module=statistics-manager&revision=2014-09-25</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:distributed-entity-ownership-service?module=distributed-entity-ownership-service&revision=2015-08-10</capability>
- </required-capabilities>
-
-</snapshot>
-
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-config</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.model</groupId>
<artifactId>model-flow-base</artifactId>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-config</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-api</artifactId>
- </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
+++ /dev/null
-/**
- * Copyright (c) 2015 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.openflowplugin.applications.config.yang.statistics_manager;
-
-import org.opendaylight.openflowplugin.applications.statistics.manager.StatisticsManager;
-import org.opendaylight.openflowplugin.applications.statistics.manager.impl.StatisticsManagerConfig;
-import org.opendaylight.openflowplugin.applications.statistics.manager.impl.StatisticsManagerImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class StatisticsManagerModule extends org.opendaylight.openflowplugin.applications.config.yang.statistics_manager.AbstractStatisticsManagerModule {
-
- private static final Logger LOG = LoggerFactory.getLogger(StatisticsManagerModule.class);
-
- private static final int MAX_NODES_FOR_COLLECTOR_DEFAULT = 16;
- private static final int MIN_REQUEST_NET_MONITOR_INTERVAL_DEFAULT = 3000;
-
- public StatisticsManagerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public StatisticsManagerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.openflowplugin.applications.config.yang.statistics_manager.StatisticsManagerModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- LOG.info("StatisticsManager module initialization.");
- final StatisticsManagerConfig config = createConfig();
- final StatisticsManager statisticsManagerProvider = new StatisticsManagerImpl(getDataBrokerDependency(), config);
- statisticsManagerProvider.setOwnershipService(getOwnershipServiceDependency());
- statisticsManagerProvider.start(getNotificationServiceDependency(), getRpcRegistryDependency());
-
- final StatisticsManager statisticsManagerProviderExposed = statisticsManagerProvider;
- LOG.info("StatisticsManager started successfully.");
- return new AutoCloseable() {
- @Override
- public void close() throws Exception {
- try {
- statisticsManagerProviderExposed.close();
- }
- catch (final Exception e) {
- LOG.error("Unexpected error by stopping StatisticsManager module", e);
- }
- LOG.info("StatisticsManager module stopped.");
- }
- };
- }
-
- private StatisticsManagerConfig createConfig() {
- final StatisticsManagerConfig.StatisticsManagerConfigBuilder builder = StatisticsManagerConfig.builder();
- if (getStatisticsManagerSettings() != null && getStatisticsManagerSettings().getMaxNodesForCollector() != null) {
- builder.setMaxNodesForCollector(getStatisticsManagerSettings().getMaxNodesForCollector());
- } else {
- LOG.warn("Load the xml ConfigSubsystem input value fail! MaxNodesForCollector value is set to {} ",
- MAX_NODES_FOR_COLLECTOR_DEFAULT);
- builder.setMaxNodesForCollector(MAX_NODES_FOR_COLLECTOR_DEFAULT);
- }
- if (getStatisticsManagerSettings() != null &&
- getStatisticsManagerSettings().getMinRequestNetMonitorInterval() != null) {
- builder.setMinRequestNetMonitorInterval(getStatisticsManagerSettings().getMinRequestNetMonitorInterval());
- } else {
- LOG.warn("Load the xml CofnigSubsystem input value fail! MinRequestNetMonitorInterval value is set to {} ",
- MIN_REQUEST_NET_MONITOR_INTERVAL_DEFAULT);
- builder.setMinRequestNetMonitorInterval(MIN_REQUEST_NET_MONITOR_INTERVAL_DEFAULT);
- }
- return builder.build();
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2015 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
- */
-
-/*
-* Generated file
-*
-* Generated from: yang module name: statistics-manager yang module local name: statistics-manager
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Thu Jan 22 17:17:48 CET 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.openflowplugin.applications.config.yang.statistics_manager;
-public class StatisticsManagerModuleFactory extends org.opendaylight.openflowplugin.applications.config.yang.statistics_manager.AbstractStatisticsManagerModuleFactory {
-
-}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.openflowplugin.applications.statistics.manager;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.statistics.manager.config.rev160509.StatisticsManagerAppConfig;
+
+/**
+ * Factory for creating StatisticsManager instances.
+ *
+ * @author Thomas Pantelis
+ */
+public interface StatisticsManagerFactory {
+ StatisticsManager newInstance(StatisticsManagerAppConfig statsManagerAppConfig, DataBroker dataBroker,
+ NotificationProviderService notifService, RpcConsumerRegistry rpcRegistry,
+ EntityOwnershipService entityOwnershipService);
+
+}
NodeIdentifierWithPredicates niWPredicates = (NodeIdentifierWithPredicates)yId.getLastPathArgument();
Map<QName, Object> keyValMap = niWPredicates.getKeyValues();
String nodeIdStr = (String)(keyValMap.get(ENTITY_NAME));
- BigInteger dpId = new BigInteger(nodeIdStr.split(":")[1]);
NodeId nodeId = new NodeId(nodeIdStr);
setNodeOwnership(nodeId, ownershipChange.isOwner());
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.openflowplugin.applications.statistics.manager.impl;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.openflowplugin.applications.statistics.manager.StatisticsManager;
+import org.opendaylight.openflowplugin.applications.statistics.manager.StatisticsManagerFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.statistics.manager.config.rev160509.StatisticsManagerAppConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of StatisticsManagerFactory.
+ *
+ * @author Thomas Pantelis
+ */
+public class StatisticsManagerFactoryImpl implements StatisticsManagerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(StatisticsManagerFactoryImpl.class);
+
+ @Override
+ public StatisticsManager newInstance(StatisticsManagerAppConfig statsManagerAppConfig, DataBroker dataBroker,
+ NotificationProviderService notifService, RpcConsumerRegistry rpcRegistry,
+ EntityOwnershipService entityOwnershipService) {
+ LOG.info("StatisticsManager module initialization.");
+
+ StatisticsManagerConfig.StatisticsManagerConfigBuilder configBuilder = StatisticsManagerConfig.builder();
+ configBuilder.setMaxNodesForCollector(statsManagerAppConfig.getMaxNodesForCollector());
+ configBuilder.setMinRequestNetMonitorInterval(statsManagerAppConfig.getMinRequestNetMonitorInterval());
+
+ StatisticsManager statisticsManager = new StatisticsManagerImpl(dataBroker, configBuilder.build());
+ statisticsManager.setOwnershipService(entityOwnershipService);
+ statisticsManager.start(notifService, rpcRegistry);
+
+ LOG.info("StatisticsManager started successfully.");
+
+ return statisticsManager;
+ }
+}
private static final String DEFAULT_ARBITRARY_BIT_MASK = "255.255.255.255";
private static final String PREFIX_SEPARATOR = "/";
private static final int IPV4_ADDRESS_LENGTH = 32;
+ private static final int BYTE_SIZE = 8;
/*
* Custom EthernetMatch is required because mac address string provided by user in EthernetMatch can be in any case
if (! (statsIpMask.length > 1 && storedIpMask.length > 1 && statsIpMask[1].equals(storedIpMask[1]))){
return false;
}
- if (InetAddresses.forString(statsIpMask[0]).equals(InetAddresses.forString(storedIpMask[0]))){
+
+ final int prefix = Integer.parseInt(statsIpMask[1]);
+ final int byteIndex = prefix/BYTE_SIZE;
+ final int lastByteBits = BYTE_SIZE - (prefix % BYTE_SIZE);
+ final InetAddress statsIp = InetAddresses.forString(statsIpMask[0]);
+ final InetAddress storedIp = InetAddresses.forString(storedIpMask[0]);
+ byte[] statsIpArr = Arrays.copyOfRange(statsIp.getAddress(),0,byteIndex+1);
+ byte[] storedIpArr = Arrays.copyOfRange(storedIp.getAddress(),0,byteIndex+1);
+ statsIpArr[byteIndex] = (byte) (statsIpArr[byteIndex] & (0XFF << lastByteBits));
+ storedIpArr[byteIndex] = (byte) (storedIpArr[byteIndex] & (0XFF << lastByteBits));
+ if(Arrays.equals(statsIpArr,storedIpArr)) {
return true;
}
return false;
}
-
static Boolean checkNullValues(final Object v1, final Object v2) {
Boolean verdict = null;
if (v1 == null && v2 != null) {
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="statsManagerFactory" class="org.opendaylight.openflowplugin.applications.statistics.manager.impl.StatisticsManagerFactoryImpl"/>
+
+ <service ref="statsManagerFactory" interface="org.opendaylight.openflowplugin.applications.statistics.manager.StatisticsManagerFactory"
+ odl:type="default"/>
+</blueprint>
\ No newline at end of file
--- /dev/null
+module statistics-manager-app-config {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:openflowplugin:app:statistics-manager:config";
+ prefix "statistics-manager-app-config";
+
+ description
+ "Configuration for Statistics Manager application.";
+
+ revision "2016-05-09" {
+ description
+ "Initial revision";
+ }
+
+ container statistics-manager-app-config {
+ leaf min-request-net-monitor-interval {
+ type int32;
+ default 3000;
+ }
+
+ leaf max-nodes-for-collector {
+ type int32;
+ default 16;
+ }
+ }
+}
\ No newline at end of file
+++ /dev/null
-module statistics-manager {
-
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:openflowplugin:app:statistics-manager";
- prefix "statistics-manager";
-
- import config { prefix config; revision-date 2013-04-05; }
- import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
- import opendaylight-entity-ownership-service { prefix ownership-service; }
-
- description
- "This module contains the base YANG definitions for
- statitics-manager implementation.";
-
- revision "2014-09-25" {
- description
- "Initial revision.";
- }
-
- identity statistics-manager {
- base config:module-type;
- config:java-name-prefix StatisticsManager;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case statistics-manager {
- when "/config:modules/config:module/config:type = 'statistics-manager'";
-
- container rpc-registry {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity mdsal:binding-rpc-registry;
- }
- }
- }
-
- container notification-service {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity mdsal:binding-notification-service;
- }
- }
- }
-
- container ownership-service {
- uses config:service-ref {
- refine type {
- mandatory false;
- config:required-identity ownership-service:entity-ownership-service;
- }
- }
- }
-
- container data-broker {
- uses config:service-ref {
- refine type {
- mandatory false;
- config:required-identity mdsal:binding-async-data-broker;
- }
- }
- }
-
- container statistics-manager-settings {
- leaf min-request-net-monitor-interval {
- type int32;
- }
- leaf max-nodes-for-collector {
- type int32;
- }
- }
- }
- }
-
-}
import static org.junit.Assert.fail;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
/**
* @author sai.marapareddy@gmail.com (arbitrary masks)
MatchComparatorHelper.layer3MatchEquals(new ArpMatchBuilder().build(), new ArpMatchBuilder().build()));
}
+ @Test
+ public void layer3MatchEqualsIpv6Test() {
+ final Ipv6MatchBuilder statsBuilder = new Ipv6MatchBuilder();
+ final Ipv6MatchBuilder storedBuilder = new Ipv6MatchBuilder();
+ assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+
+ statsBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:5D99/64"));
+ storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:4D99/64"));
+ assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+
+ statsBuilder.setIpv6Destination(new Ipv6Prefix("aabb:1234:2acf:000d:0000:0000:0000:5d99/64"));
+ storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:4D99/64"));
+ assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+
+ statsBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000C:0000:0000:0000:5D99/64"));
+ storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:4D99/64"));
+ assertEquals(false, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+
+ statsBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000C:0000:0000:0000:5D99/63"));
+ storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:4D99/63"));
+ assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+
+ statsBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:5D99/63"));
+ storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000E:0000:0000:0000:4D99/63"));
+ assertEquals(false, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+ }
+
@Test
public void layer3MatchEqualsIpv4ArbitraryMaskTest(){
final Ipv4MatchBuilder statsBuilder = new Ipv4MatchBuilder();
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-api</artifactId>
- </dependency>
</dependencies>
<build>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
</plugin>
-
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-artifacts</id>
- <goals>
- <goal>attach-artifact</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <artifacts>
- <artifact>
- <file>${project.build.directory}/classes/initial/69-table-miss-enforcer.xml</file>
- <type>xml</type>
- <classifier>config</classifier>
- </artifact>
- </artifacts>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
</project>
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.Callable;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
* Created by Martin Bobak mbobak@cisco.com on 8/27/14.
*/
public class LLDPPacketPuntEnforcer implements DataChangeListener {
-
+ private static final long STARTUP_LOOP_TICK = 500L;
+ private static final int STARTUP_LOOP_MAX_RETRIES = 8;
private static final short TABLE_ID = (short) 0;
private static final String LLDP_PUNT_WHOLE_PACKET_FLOW = "LLDP_PUNT_WHOLE_PACKET_FLOW";
private static final String DEFAULT_FLOW_ID = "42";
private final SalFlowService flowService;
+ private final DataBroker dataBroker;
+ private ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
- public LLDPPacketPuntEnforcer(SalFlowService flowService) {
+ public LLDPPacketPuntEnforcer(SalFlowService flowService, DataBroker dataBroker) {
this.flowService = flowService;
+ this.dataBroker = dataBroker;
+ }
+
+ public void start() {
+ final InstanceIdentifier<FlowCapableNode> path = InstanceIdentifier.create(Nodes.class).child(Node.class).
+ augmentation(FlowCapableNode.class);
+ SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
+ try {
+ dataChangeListenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<DataChangeListener>>() {
+ @Override
+ public ListenerRegistration<DataChangeListener> call() throws Exception {
+ return dataBroker.registerDataChangeListener(
+ LogicalDatastoreType.OPERATIONAL,
+ path, LLDPPacketPuntEnforcer.this, AsyncDataBroker.DataChangeScope.BASE);
+ }
+ });
+ } catch (Exception e) {
+ throw new IllegalStateException("registerDataChangeListener failed", e);
+ }
+ }
+
+ public void close() {
+ if(dataChangeListenerRegistration != null) {
+ dataChangeListenerRegistration.close();
+ }
}
@Override
+++ /dev/null
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.table.miss.enforcer.rev140326;
-
-import java.util.concurrent.Callable;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.openflowplugin.applications.tableMissEnforcer.LLDPPacketPuntEnforcer;
-import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class LLDPPacketPuntEnforcerModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.table.miss.enforcer.rev140326.AbstractLLDPPacketPuntEnforcerModule {
- private static final long STARTUP_LOOP_TICK = 500L;
- private static final int STARTUP_LOOP_MAX_RETRIES = 8;
- private static final Logger LOG = LoggerFactory.getLogger(LLDPPacketPuntEnforcerModule.class);
-
- public LLDPPacketPuntEnforcerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public LLDPPacketPuntEnforcerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.table.miss.enforcer.rev140326.LLDPPacketPuntEnforcerModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- final InstanceIdentifier<FlowCapableNode> path = InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
- final SalFlowService salFlowService = getRpcRegistryDependency().getRpcService(SalFlowService.class);
-
- ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
- SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
- try {
- dataChangeListenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<DataChangeListener>>() {
- @Override
- public ListenerRegistration<DataChangeListener> call() throws Exception {
- return getDataBrokerDependency().registerDataChangeListener(
- LogicalDatastoreType.OPERATIONAL,
- path,
- new LLDPPacketPuntEnforcer(salFlowService),
- AsyncDataBroker.DataChangeScope.BASE);
- }
- });
- } catch (Exception e) {
- LOG.warn("data listener registration failed: {}", e.getMessage());
- LOG.debug("data listener registration failed.. ", e);
- throw new IllegalStateException("LLDPPacketPuntEnforcer startup fail! System needs restart.", e);
- }
- return dataChangeListenerRegistration;
- }
-
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: table-miss-enforcer yang module local name: table-miss-enforcer
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Mon Sep 08 15:26:18 CEST 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.table.miss.enforcer.rev140326;
-public class LLDPPacketPuntEnforcerModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.applications.table.miss.enforcer.rev140326.AbstractLLDPPacketPuntEnforcerModuleFactory {
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
-Copyright (c) 2014 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
--->
-<snapshot>
- <configuration>
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:applications:table-miss-enforcer">prefix:table-miss-enforcer</type>
- <name>table-miss-enforcer</name>
- <data-broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
- <name>binding-data-broker</name>
- </data-broker>
- <rpc-registry>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
- <name>binding-rpc-broker</name>
- </rpc-registry>
- </module>
-
- </modules>
- </data>
- </configuration>
-</snapshot>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
+
+ <odl:rpc-service id="flowService" interface="org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService"/>
+
+ <bean id="LLDPPacketPuntEnforcer" class="org.opendaylight.openflowplugin.applications.tableMissEnforcer.LLDPPacketPuntEnforcer"
+ init-method="start" destroy-method="close">
+ <argument ref="flowService"/>
+ <argument ref="dataBroker"/>
+ </bean>
+</blueprint>
\ No newline at end of file
+++ /dev/null
-module table-miss-enforcer {
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:openflow:applications:table-miss-enforcer";
- prefix "table-miss-enforcer";
- import config {prefix config; revision-date 2013-04-05;}
- import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
-
- description
- "table-miss-enforcer-custom-config-impl";
-
- revision "2014-03-26" {
- description
- "Initial revision";
- }
-
- identity table-miss-enforcer {
- base "config:module-type";
- config:java-name-prefix LLDPPacketPuntEnforcer;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case table-miss-enforcer {
- when "/config:modules/config:module/config:type = 'table-miss-enforcer'";
- container rpc-registry {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity mdsal:binding-rpc-registry;
- }
- }
- }
- container data-broker {
- uses config:service-ref {
- refine type {
- mandatory false;
- config:required-identity mdsal:binding-async-data-broker;
- }
- }
- }
- }
- }
-}
*/
@Test
public void testCreateFlow() {
- LLDPPacketPuntEnforcer lldpDataChangeListener = new LLDPPacketPuntEnforcer(flowService);
+ LLDPPacketPuntEnforcer lldpDataChangeListener = new LLDPPacketPuntEnforcer(flowService, null);
evaluateFlow(lldpDataChangeListener.createFlow());
}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
-Copyright (c) 2014 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
--->
-<snapshot>
- <required-capabilities>
- <!--<capability>urn:opendaylight:params:xml:ns:yang:southbound:impl?module=southbound-impl&revision=2015-01-05</capability>-->
- <capability>urn:opendaylight:inventory?module=opendaylight-inventory&revision=2013-08-19</capability>
- <capability>urn:opendaylight:flow:inventory?module=flow-node-inventory&revision=2013-08-19</capability>
- <capability>urn:opendaylight:flow:types?module=opendaylight-flow-types&revision=2013-10-26</capability>
- <capability>urn:opendaylight:packet:service?module=packet-processing&revision=2013-07-09</capability>
- </required-capabilities>
- <configuration>
-
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:topology-lldp-discovery:impl">prefix:topology-lldp-discovery-impl</type>
- <name>topology-lldp-discovery-default</name>
- <broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
- <name>binding-osgi-broker</name>
- </broker>
- <lldp-secure-key>aa9251f8-c7c0-4322-b8d6-c3a84593bda3</lldp-secure-key>
- </module>
- </modules>
- </data>
- </configuration>
-</snapshot>
*/
package org.opendaylight.openflowplugin.applications.topology.lldp;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class LLDPActivator implements BindingAwareProvider, AutoCloseable {
+public class LLDPActivator implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(LLDPActivator.class);
- private static LLDPDiscoveryProvider provider = new LLDPDiscoveryProvider();
+
private static String lldpSecureKey;
- public LLDPActivator(String secureKey) {
+ private final ListenerRegistration<NotificationListener> lldpNotificationRegistration;
+
+ public LLDPActivator(NotificationProviderService notificationService, LLDPDiscoveryListener lldpDiscoveryListener,
+ String secureKey) {
lldpSecureKey = secureKey;
- }
- public void onSessionInitiated(final ProviderContext session) {
- DataProviderService dataService = session.<DataProviderService>getSALService(DataProviderService.class);
- provider.setDataService(dataService);
- NotificationProviderService notificationService = session.<NotificationProviderService>getSALService(NotificationProviderService.class);
- provider.setNotificationService(notificationService);
- provider.start();
+ LOG.info("Starting LLDPActivator with lldpSecureKey: {}", lldpSecureKey);
+
+ lldpNotificationRegistration = notificationService.registerNotificationListener(lldpDiscoveryListener);
+
+ LOG.info("LLDPDiscoveryListener started.");
}
@Override
- public void close() throws Exception {
- if(provider != null) {
- try {
- provider.close();
- } catch (Exception e) {
- LOG.warn("Exception when closing down topology-lldp-discovery",e);
- }
- }
+ public void close() {
+ lldpNotificationRegistration.close();
+
+ LOG.info("LLDPDiscoveryListener stopped.");
}
public static String getLldpSecureKey() {
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-class LLDPDiscoveryListener implements PacketProcessingListener {
+public class LLDPDiscoveryListener implements PacketProcessingListener {
private static final Logger LOG = LoggerFactory.getLogger(LLDPDiscoveryListener.class);
- private LLDPLinkAger lldpLinkAger;
- private NotificationProviderService notificationService;
+ private final LLDPLinkAger lldpLinkAger;
+ private final NotificationProviderService notificationService;
- LLDPDiscoveryListener(NotificationProviderService notificationService) {
+ public LLDPDiscoveryListener(NotificationProviderService notificationService, LLDPLinkAger lldpLinkAger) {
this.notificationService = notificationService;
+ this.lldpLinkAger = lldpLinkAger;
}
+ @Override
public void onPacketReceived(PacketReceived lldp) {
NodeConnectorRef src = LLDPDiscoveryUtils.lldpToNodeConnectorRef(lldp.getPayload(), true);
if(src != null) {
lldpLinkAger.put(ld);
}
}
-
- public void setLldpLinkAger(LLDPLinkAger lldpLinkAger) {
- this.lldpLinkAger = lldpLinkAger;
- }
-}
+}
\ 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.openflowplugin.applications.topology.lldp;
-
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.openflowplugin.applications.topology.lldp.utils.LLDPDiscoveryUtils;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.NotificationListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class LLDPDiscoveryProvider implements AutoCloseable {
- private static final Logger LOG = LoggerFactory.getLogger(LLDPDiscoveryProvider.class);
- private DataProviderService dataService;
- private NotificationProviderService notificationService;
-
- private ListenerRegistration<NotificationListener> listenerRegistration;
- private LLDPLinkAger lldpLinkAger;
-
- public DataProviderService getDataService() {
- return this.dataService;
- }
-
- public void setDataService(final DataProviderService dataService) {
- this.dataService = dataService;
- }
-
- public NotificationProviderService getNotificationService() {
- return this.notificationService;
- }
-
- public void setNotificationService(final NotificationProviderService notificationService) {
- this.notificationService = notificationService;
- }
-
- public void start() {
- lldpLinkAger = new LLDPLinkAger(LLDPDiscoveryUtils.LLDP_INTERVAL, LLDPDiscoveryUtils.LLDP_EXPIRATION_TIME);
- lldpLinkAger.setNotificationService(notificationService);
-
- LLDPDiscoveryListener committer = new LLDPDiscoveryListener(notificationService);
- committer.setLldpLinkAger(lldpLinkAger);
-
- ListenerRegistration<NotificationListener> registerNotificationListener =
- notificationService.registerNotificationListener(committer);
- this.listenerRegistration = registerNotificationListener;
- LOG.info("LLDPDiscoveryListener Started.");
- }
-
- public void close() {
- try {
- LOG.info("LLDPDiscoveryListener stopped.");
- if (this.listenerRegistration!=null) {
- this.listenerRegistration.close();
- }
- lldpLinkAger.close();
- } catch (Exception e) {
- throw new Error(e);
- }
- }
-}
public class LLDPLinkAger implements AutoCloseable {
private final long linkExpirationTime;
- private Map<LinkDiscovered, Date> linkToDate;
- private Timer timer;
- private NotificationProviderService notificationService;
+ private final Map<LinkDiscovered, Date> linkToDate;
+ private final Timer timer;
+ private final NotificationProviderService notificationService;
/**
* default ctor - start timer
*/
- public LLDPLinkAger(final long lldpInterval, final long linkExpirationTime) {
+ public LLDPLinkAger(final long lldpInterval, final long linkExpirationTime,
+ final NotificationProviderService notificationService) {
this.linkExpirationTime = linkExpirationTime;
+ this.notificationService = notificationService;
linkToDate = new ConcurrentHashMap<>();
timer = new Timer();
timer.schedule(new LLDPAgingTask(), 0, lldpInterval);
linkToDate.clear();
}
- public void setNotificationService(NotificationProviderService notificationService) {
- this.notificationService = notificationService;
- }
-
private class LLDPAgingTask extends TimerTask {
@Override
*/
package org.opendaylight.openflowplugin.applications.topology.lldp.utils;
-import org.apache.commons.lang3.ArrayUtils;
-import java.nio.charset.Charset;
import com.google.common.hash.HashCode;
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+import java.lang.management.ManagementFactory;
+import java.nio.charset.Charset;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import org.apache.commons.lang3.ArrayUtils;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.CustomTLVKey;
import org.opendaylight.controller.liblldp.Ethernet;
import org.opendaylight.controller.liblldp.LLDP;
-import org.opendaylight.controller.liblldp.BitBufferHelper;
import org.opendaylight.controller.liblldp.LLDPTLV;
import org.opendaylight.controller.liblldp.NetUtils;
-import com.google.common.hash.Hasher;
-import com.google.common.hash.Hashing;
-import com.google.common.hash.HashFunction;
import org.opendaylight.openflowplugin.applications.topology.lldp.LLDPActivator;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import java.util.Arrays;
-import java.security.NoSuchAlgorithmException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-import java.lang.management.ManagementFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.controller.liblldp.CustomTLVKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LLDPDiscoveryUtils {
private static final Logger LOG = LoggerFactory.getLogger(LLDPDiscoveryUtils.class);
- // Send LLDP every five seconds
- public static final Long LLDP_INTERVAL = (long) (1000*5);
-
- // Let up to three intervals pass before we decide we are expired.
- public static final Long LLDP_EXPIRATION_TIME = LLDP_INTERVAL*3;
-
public static String macToString(byte[] mac) {
StringBuilder b = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
+++ /dev/null
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.lldp.discovery.impl.rev150530;
-
-import org.opendaylight.openflowplugin.applications.topology.lldp.LLDPActivator;
-
-public class TopologyLldpDiscoveryImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.lldp.discovery.impl.rev150530.AbstractTopologyLldpDiscoveryImplModule {
- public TopologyLldpDiscoveryImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public TopologyLldpDiscoveryImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.lldp.discovery.impl.rev150530.TopologyLldpDiscoveryImplModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- LLDPActivator provider = new LLDPActivator(getLldpSecureKey());
- getBrokerDependency().registerProvider(provider);
- return provider;
- }
-
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: topology-lldp-discovery-impl yang module local name: topology-lldp-discovery-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Sat May 30 20:35:29 PDT 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.lldp.discovery.impl.rev150530;
-public class TopologyLldpDiscoveryImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.lldp.discovery.impl.rev150530.AbstractTopologyLldpDiscoveryImplModuleFactory {
-
-}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="notificationService" interface="org.opendaylight.controller.sal.binding.api.NotificationProviderService"/>
+
+ <odl:clustered-app-config id="topologyLLDPConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.lldp.discovery.config.rev160511.TopologyLldpDiscoveryConfig">
+ <odl:default-config><![CDATA[
+ <topology-lldp-discovery-config xmlns="urn:opendaylight:params:xml:ns:yang:topology-lldp-discovery:config">
+ <lldp-secure-key>aa9251f8-c7c0-4322-b8d6-c3a84593bda3</lldp-secure-key>
+ </topology-lldp-discovery-config>
+ ]]></odl:default-config>
+ </odl:clustered-app-config>
+
+ <bean id="lldpLinkAger" class="org.opendaylight.openflowplugin.applications.topology.lldp.LLDPLinkAger"
+ destroy-method="close">
+ <!-- Interval to send LLDP (five seconds) -->
+ <argument value="5000"/>
+ <!-- Expiration interval for aging out links (3 * the interval) -->
+ <argument value="15000"/>
+ <argument ref="notificationService"/>
+ </bean>
+
+ <bean id="lldpDiscoveryListener" class="org.opendaylight.openflowplugin.applications.topology.lldp.LLDPDiscoveryListener">
+ <argument ref="notificationService"/>
+ <argument ref="lldpLinkAger"/>
+ </bean>
+
+ <bean id="LLDPActivator" class="org.opendaylight.openflowplugin.applications.topology.lldp.LLDPActivator"
+ destroy-method="close">
+ <argument ref="notificationService"/>
+ <argument ref="lldpDiscoveryListener"/>
+ <argument>
+ <bean factory-ref="topologyLLDPConfig" factory-method="getLldpSecureKey"/>
+ </argument>
+ </bean>
+</blueprint>
\ No newline at end of file
--- /dev/null
+module topology-lldp-discovery-config {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:topology-lldp-discovery:config";
+ prefix "topology-lldp-discovery-config";
+
+ description
+ "Configuration for Topology LLDP discovery application.";
+
+ revision "2016-05-11" {
+ description
+ "Initial revision.";
+ }
+
+ container topology-lldp-discovery-config {
+ leaf lldp-secure-key {
+ description "Provided key will be used to generate LLDP custom security hash";
+ type string;
+ mandatory true;
+ }
+ }
+}
\ No newline at end of file
+++ /dev/null
-module topology-lldp-discovery-impl {
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:topology-lldp-discovery:impl";
- prefix "topology-lldp-discovery-impl";
-
- import config { prefix config; revision-date 2013-04-05; }
- import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
-
- description
- "Service definition for topology-lldp-discovery";
-
- revision "2015-05-30" {
- description
- "Initial revision";
- }
-
- identity topology-lldp-discovery-impl {
- base config:module-type;
- config:java-name-prefix TopologyLldpDiscoveryImpl;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case topology-lldp-discovery-impl {
- when "/config:modules/config:module/config:type = 'topology-lldp-discovery-impl'";
- container broker {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity md-sal-binding:binding-broker-osgi-registry;
- }
- }
- }
- leaf lldp-secure-key {
- description "Provided key will be used to generate LLDP custom security hash";
- type string;
- }
- }
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
-Copyright (c) 2014 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
--->
-<snapshot>
- <required-capabilities>
- <!--<capability>urn:opendaylight:params:xml:ns:yang:southbound:impl?module=southbound-impl&revision=2015-01-05</capability>-->
- <capability>urn:opendaylight:inventory?module=opendaylight-inventory&revision=2013-08-19</capability>
- <capability>urn:opendaylight:flow:inventory?module=flow-node-inventory&revision=2013-08-19</capability>
- <capability>urn:opendaylight:flow:types?module=opendaylight-flow-types&revision=2013-10-26</capability>
- <capability>urn:TBD:params:xml:ns:yang:network-topology?module=network-topology&revision=2013-10-21</capability>
- <capability>urn:opendaylight:flow:topology:discovery?module=flow-topology-discovery&revision=2013-08-19</capability>
- </required-capabilities>
- <configuration>
-
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:topology-manager:impl">prefix:topology-manager-impl</type>
- <name>topology-manager-default</name>
- <broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
- <name>binding-osgi-broker</name>
- </broker>
- </module>
- </modules>
- </data>
- </configuration>
-</snapshot>
*/
package org.opendaylight.openflowplugin.applications.topology.manager;
-import java.util.concurrent.ExecutionException;
-
import com.google.common.base.Optional;
+import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class FlowCapableTopologyProvider implements BindingAwareProvider, AutoCloseable {
+public class FlowCapableTopologyProvider implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(FlowCapableTopologyProvider.class);
- private ListenerRegistration<NotificationListener> listenerRegistration;
- private Thread thread;
- private TerminationPointChangeListenerImpl terminationPointChangeListener;
- private NodeChangeListenerImpl nodeChangeListener;
static final String TOPOLOGY_ID = "flow:1";
+ private final DataBroker dataBroker;
+ private final NotificationProviderService notificationService;
+ private final OperationProcessor processor;
+ private ListenerRegistration<NotificationListener> listenerRegistration;
+
+ public FlowCapableTopologyProvider(DataBroker dataBroker, NotificationProviderService notificationService,
+ OperationProcessor processor) {
+ this.dataBroker = dataBroker;
+ this.notificationService = notificationService;
+ this.processor = processor;
+ }
+
/**
* Gets called on start of a bundle.
- *
- * @param session
*/
- @Override
- public synchronized void onSessionInitiated(final ProviderContext session) {
- final DataBroker dataBroker = session.getSALService(DataBroker.class);
- final NotificationProviderService notificationService = session.getSALService(NotificationProviderService.class);
-
+ public void start() {
final TopologyKey key = new TopologyKey(new TopologyId(TOPOLOGY_ID));
final InstanceIdentifier<Topology> path = InstanceIdentifier
.create(NetworkTopology.class)
.child(Topology.class, key);
- final OperationProcessor processor = new OperationProcessor(dataBroker);
final FlowCapableTopologyExporter listener = new FlowCapableTopologyExporter(processor, path);
this.listenerRegistration = notificationService.registerNotificationListener(listener);
- this.terminationPointChangeListener = new TerminationPointChangeListenerImpl(dataBroker, processor);
- nodeChangeListener = new NodeChangeListenerImpl(dataBroker, processor);
if(!isFlowTopologyExist(dataBroker, path)){
final ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
}
}
- thread = new Thread(processor);
- thread.setDaemon(true);
- thread.setName("FlowCapableTopologyExporter-" + TOPOLOGY_ID);
- thread.start();
+ LOG.info("FlowCapableTopologyProvider started");
}
@Override
- public synchronized void close() throws InterruptedException {
+ public void close() {
LOG.info("FlowCapableTopologyProvider stopped.");
if (this.listenerRegistration != null) {
try {
}
listenerRegistration = null;
}
- unregisterListener(terminationPointChangeListener);
- unregisterListener(nodeChangeListener);
- if (thread != null) {
- thread.interrupt();
- thread.join();
- thread = null;
- }
- }
-
- private static void unregisterListener(final AutoCloseable listenerToClose) {
- if (listenerToClose != null) {
- try {
- listenerToClose.close();
- } catch (Exception e) {
- LOG.warn("Failed to close listener registration: {}", e.getMessage());
- LOG.debug("Failed to close listener registration.. ", e);
- }
- }
}
private boolean isFlowTopologyExist(final DataBroker dataBroker,
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final class OperationProcessor implements AutoCloseable, Runnable, TransactionChainListener {
+public final class OperationProcessor implements AutoCloseable, Runnable, TransactionChainListener {
private static final Logger LOG = LoggerFactory.getLogger(OperationProcessor.class);
private static final int MAX_TRANSACTION_OPERATIONS = 100;
private static final int OPERATION_QUEUE_DEPTH = 500;
private final BlockingQueue<TopologyOperation> queue = new LinkedBlockingQueue<>(OPERATION_QUEUE_DEPTH);
private final DataBroker dataBroker;
+ private final Thread thread;
private BindingTransactionChain transactionChain;
private volatile boolean finishing = false;
- OperationProcessor(final DataBroker dataBroker) {
+ public OperationProcessor(final DataBroker dataBroker) {
this.dataBroker = Preconditions.checkNotNull(dataBroker);
transactionChain = this.dataBroker.createTransactionChain(this);
+
+ thread = new Thread(this);
+ thread.setDaemon(true);
+ thread.setName("FlowCapableTopologyExporter-" + FlowCapableTopologyProvider.TOPOLOGY_ID);
}
void enqueueOperation(final TopologyOperation task) {
}
}
+ public void start() {
+ thread.start();
+ }
+
@Override
public void run() {
while (!finishing) {
transactionChain = dataBroker.createTransactionChain(this);
cleanDataStoreOperQueue();
} catch (final InterruptedException e) {
- LOG.warn("Stat Manager DS Operation thread interupted!", e);
+ // This should mean we're shutting down.
+ LOG.debug("Stat Manager DS Operation thread interupted!", e);
finishing = true;
} catch (final Exception e) {
LOG.warn("Stat DataStore Operation executor fail!", e);
}
@Override
- public void close() throws Exception {
+ public void close() {
+ thread.interrupt();
+ try {
+ thread.join();
+ } catch(InterruptedException e) {
+ LOG.debug("Join of thread {} was interrupted", thread.getName(), e);
+ }
+
if (transactionChain != null) {
transactionChain.close();
}
+ LOG.debug("OperationProcessor closed");
}
}
+++ /dev/null
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.manager.impl.rev150530;
-
-import org.opendaylight.openflowplugin.applications.topology.manager.FlowCapableTopologyProvider;
-
-public class TopologyLldpDiscoveryImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.manager.impl.rev150530.AbstractTopologyLldpDiscoveryImplModule {
- public TopologyLldpDiscoveryImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public TopologyLldpDiscoveryImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.manager.impl.rev150530.TopologyLldpDiscoveryImplModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- FlowCapableTopologyProvider provider = new FlowCapableTopologyProvider();
- getBrokerDependency().registerProvider(provider);
- return provider;
- }
-
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: topology-manager-impl yang module local name: topology-manager-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Sat May 30 21:28:43 PDT 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.manager.impl.rev150530;
-public class TopologyLldpDiscoveryImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.manager.impl.rev150530.AbstractTopologyLldpDiscoveryImplModuleFactory {
-
-}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
+ <reference id="notificationService" interface="org.opendaylight.controller.sal.binding.api.NotificationProviderService"/>
+
+ <bean id="operationProcessor" class="org.opendaylight.openflowplugin.applications.topology.manager.OperationProcessor"
+ init-method="start" destroy-method="close">
+ <argument ref="dataBroker"/>
+ </bean>
+
+ <bean id="termPointChangeListener" class="org.opendaylight.openflowplugin.applications.topology.manager.TerminationPointChangeListenerImpl"
+ destroy-method="close">
+ <argument ref="dataBroker"/>
+ <argument ref="operationProcessor"/>
+ </bean>
+
+ <bean id="nodeChangeListener" class="org.opendaylight.openflowplugin.applications.topology.manager.NodeChangeListenerImpl"
+ destroy-method="close">
+ <argument ref="dataBroker"/>
+ <argument ref="operationProcessor"/>
+ </bean>
+
+ <bean id="topologyProvider" class="org.opendaylight.openflowplugin.applications.topology.manager.FlowCapableTopologyProvider"
+ init-method="start" destroy-method="close">
+ <argument ref="dataBroker"/>
+ <argument ref="notificationService"/>
+ <argument ref="operationProcessor"/>
+ </bean>
+</blueprint>
\ No newline at end of file
+++ /dev/null
-module topology-manager-impl {
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:topology-manager:impl";
- prefix "topology-manager-impl";
-
- import config { prefix config; revision-date 2013-04-05; }
- import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
-
- description
- "Service definition for topology-manager";
-
- revision "2015-05-30" {
- description
- "Initial revision";
- }
-
- identity topology-manager-impl {
- base config:module-type;
- config:java-name-prefix TopologyLldpDiscoveryImpl;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case topology-manager-impl {
- when "/config:modules/config:module/config:type = 'topology-manager-impl'";
- container broker {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity md-sal-binding:binding-broker-osgi-registry;
- }
- }
- }
- }
- }
-}
</dependency>
<dependency>
<groupId>${project.groupId}.applications</groupId>
- <artifactId>forwardingrules-manager-config</artifactId>
+ <artifactId>forwardingrules-sync</artifactId>
<version>${project.version}</version>
- <classifier>config</classifier>
- <type>xml</type>
</dependency>
<dependency>
<groupId>${project.groupId}.applications</groupId>
- <artifactId>inventory-manager</artifactId>
+ <artifactId>forwardingrules-sync</artifactId>
<version>${project.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
</dependency>
<dependency>
<groupId>${project.groupId}.applications</groupId>
<artifactId>inventory-manager</artifactId>
<version>${project.version}</version>
- <type>xml</type>
- <classifier>config</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}.applications</groupId>
<artifactId>topology-lldp-discovery</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}.applications</groupId>
- <artifactId>topology-lldp-discovery</artifactId>
- <version>${project.version}</version>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>${project.groupId}.applications</groupId>
<artifactId>topology-manager</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}.applications</groupId>
- <artifactId>topology-manager</artifactId>
- <version>${project.version}</version>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>${project.groupId}.applications</groupId>
<artifactId>of-switch-config-pusher</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}.applications</groupId>
- <artifactId>of-switch-config-pusher</artifactId>
- <version>${project.version}</version>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
- <dependency>
- <groupId>${project.groupId}.applications</groupId>
- <artifactId>statistics-manager-config</artifactId>
- <version>${project.version}</version>
- <classifier>config</classifier>
- <type>xml</type>
- </dependency>
<dependency>
<groupId>${project.groupId}.applications</groupId>
<artifactId>table-miss-enforcer</artifactId>
<type>xml</type>
<classifier>config</classifier>
</dependency>
- <dependency>
- <groupId>${project.groupId}.applications</groupId>
- <artifactId>lldp-speaker</artifactId>
- <version>${project.version}</version>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>openflowplugin-controller-config</artifactId>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>features-openflowplugin</artifactId>
+ <artifactId>features-openflowplugin-he</artifactId>
<version>${project.version}</version>
<classifier>features</classifier>
<type>xml</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>features-openflowplugin-li</artifactId>
+ <artifactId>features-openflowplugin</artifactId>
<version>${project.version}</version>
<classifier>features</classifier>
<type>xml</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>features-openflowplugin-extension</artifactId>
+ <artifactId>features-openflowplugin-extension-he</artifactId>
<version>${project.version}</version>
<classifier>features</classifier>
<type>xml</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>features-openflowplugin-extension-li</artifactId>
+ <artifactId>features-openflowplugin-extension</artifactId>
<version>${project.version}</version>
<classifier>features</classifier>
<type>xml</type>
</dependency>
<dependency>
<groupId>${project.groupId}.applications</groupId>
- <artifactId>old-notification-supplier</artifactId>
+ <artifactId>notification-supplier</artifactId>
<version>${project.version}</version>
<type>xml</type>
<classifier>config</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}.applications</groupId>
- <artifactId>old-notification-supplier</artifactId>
+ <artifactId>notification-supplier</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependency>
<!-- openflowplugin feature -->
<dependency>
- <artifactId>features-openflowplugin</artifactId>
+ <artifactId>features-openflowplugin-he</artifactId>
<groupId>org.opendaylight.openflowplugin</groupId>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
</dependency>
<dependency>
- <artifactId>features-openflowplugin-li</artifactId>
+ <artifactId>features-openflowplugin</artifactId>
<groupId>org.opendaylight.openflowplugin</groupId>
<classifier>features</classifier>
<type>xml</type>
<!-- openflowplugin extension feature -->
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>features-openflowplugin-extension</artifactId>
+ <artifactId>features-openflowplugin-extension-he</artifactId>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>features-openflowplugin-extension-li</artifactId>
+ <artifactId>features-openflowplugin-extension</artifactId>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-api</artifactId>
- </dependency>
</dependencies>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
- <plugin>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>generate-sources</goal>
- </goals>
- <configuration>
- <codeGenerators>
- <generator>
- <codeGeneratorClass>
- org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
- </codeGeneratorClass>
- <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
- <additionalConfiguration>
- <namespaceToPackage1>
- urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
- </namespaceToPackage1>
- </additionalConfiguration>
- </generator>
- <generator>
- <codeGeneratorClass>
- org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
- </codeGeneratorClass>
- <outputBaseDir>${project.build.directory}/generated-sources/sal</outputBaseDir>
- </generator>
- <generator>
- <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
- <outputBaseDir>${project.build.directory}/site/models</outputBaseDir>
- </generator>
- </codeGenerators>
- <inspectDependencies>true</inspectDependencies>
- </configuration>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${config.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.mdsal</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${mdsal.model.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-artifacts</id>
- <goals>
- <goal>attach-artifact</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <artifacts>
- <artifact>
- <file>${project.build.directory}/classes/initial/69-drop-test.xml</file>
- <type>xml</type>
- <classifier>config</classifier>
- </artifact>
- </artifacts>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
</project>
+++ /dev/null
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.config.openflow.test.droptest.rev150327;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.NotificationService;
-import org.opendaylight.openflowplugin.droptestkaraf.DropTestProviderImpl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DropTestProviderModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.config.openflow.test.droptest.rev150327.AbstractDropTestProviderModule {
- private static final Logger LOG = LoggerFactory.getLogger(DropTestProviderModule.class);
-
- public DropTestProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public DropTestProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.config.openflow.test.droptest.rev150327.DropTestProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void customValidation() {
- // add custom validation form module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- LOG.debug("Starting drop-test provider module.");
- DataBroker dataBroker = getDataBrokerDependency();
- NotificationService notificationAdapterDependency = getNotificationAdapterDependency();
- SalFlowService salFlowService = getRpcRegistryDependency().getRpcService(SalFlowService.class);
- DropTestProviderImpl dropTestProvider = new DropTestProviderImpl(dataBroker, notificationAdapterDependency, salFlowService);
- LOG.info("Drop-test provider module initialized.");
- return dropTestProvider;
- }
-
-}
+++ /dev/null
-/*
-* Generated file
-*
-* Generated from: yang module name: drop-test-provider yang module local name: drop-test-provider
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Sun Apr 26 11:04:30 CEST 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.config.openflow.test.droptest.rev150327;
-public class DropTestProviderModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.config.openflow.test.droptest.rev150327.AbstractDropTestProviderModuleFactory {
-
-}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" odl:type="pingpong"/>
+ <reference id="notificationService" interface="org.opendaylight.controller.md.sal.binding.api.NotificationService"/>
+
+ <odl:rpc-service id="flowService"
+ interface="org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService"/>
+
+ <bean id="dropTestProvider" class="org.opendaylight.openflowplugin.droptestkaraf.DropTestProviderImpl">
+ <argument ref="dataBroker"/>
+ <argument ref="notificationService"/>
+ <argument ref="flowService"/>
+ </bean>
+</blueprint>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Copyright (c) 2015 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
- -->
-
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-
-<snapshot>
- <configuration>
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:config:openflow:test:droptest">prefix:drop-test-provider</type>
- <name>drop-test-provider</name>
- <data-broker>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
- <name>binding-data-broker</name>
- </data-broker>
- <rpc-registry>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
- <name>binding-rpc-broker</name>
- </rpc-registry>
- <notification-adapter>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-new-notification-service</type>
- <name>binding-notification-adapter</name>
- </notification-adapter>
- </module>
- </modules>
- </data>
- </configuration>
-</snapshot>
\ No newline at end of file
+++ /dev/null
-module drop-test-provider {
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:config:openflow:test:droptest";
- prefix "drop-test-provider";
-
- import config {prefix config; revision-date 2013-04-05;}
- import rpc-context { prefix rpcx; revision-date 2013-06-17; }
- import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
- import opendaylight-sal-binding-broker-impl { prefix sal-broker; revision-date 2013-10-28;}
-
- description
- "drop-test-provider";
-
- revision "2015-03-27" {
- description
- "Drop test implementation.";
- }
-
- identity drop-test-provider {
- base config:module-type;
- config:java-name-prefix DropTestProvider;
- }
-
- augment "/config:modules/config:module/config:configuration" {
- case drop-test-provider {
- when "/config:modules/config:module/config:type = 'drop-test-provider'";
-
- container data-broker {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity md-sal-binding:binding-async-data-broker;
- }
- }
- }
- container rpc-registry {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity md-sal-binding:binding-rpc-registry;
- }
- }
- }
- container notification-adapter {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity sal-broker:binding-new-notification-service;
- }
- }
- }
- }
- }
-}
</parent>
<groupId>org.opendaylight.openflowplugin</groupId>
<version>0.3.0-SNAPSHOT</version>
- <artifactId>features-openflowplugin-extension-li</artifactId>
+ <artifactId>features-openflowplugin-extension-he</artifactId>
<packaging>jar</packaging>
<!-- feature dependencies -->
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>features-openflowplugin-li</artifactId>
+ <artifactId>features-openflowplugin-he</artifactId>
<classifier>features</classifier>
<type>xml</type>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
-<features name="openflowplugin-extension-li-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+<features name="openflowplugin-extension-he-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
- <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-li/${project.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-he/${project.version}/xml/features</repository>
- <feature name="odl-openflowplugin-nxm-extensions-li" description="OpenDaylight :: Openflow Plugin :: Nicira Extensions" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-southbound-li</feature>
+ <feature name="odl-openflowplugin-nxm-extensions-he" description="OpenDaylight :: Openflow Plugin :: Nicira Extensions" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-southbound-he</feature>
<configfile finalname="etc/opendaylight/karaf/43-openflowjava-nx-config.xml">mvn:org.opendaylight.openflowplugin/openflowplugin-extension-nicira-config/{{VERSION}}/xml/config</configfile>
<bundle>mvn:org.opendaylight.openflowplugin/openflowjava-extension-nicira-api/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin/openflowjava-extension-nicira/{{VERSION}}</bundle>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
registrator.registerActionSerializer(SetNspCodec.SERIALIZER_KEY, NiciraActionCodecs.SET_NSP_CODEC);
registrator.registerActionDeserializer(SetNshc1Codec.DESERIALIZER_KEY, NiciraActionCodecs.SET_NSC1_CODEC);
registrator.registerActionSerializer(SetNshc1Codec.SERIALIZER_KEY, NiciraActionCodecs.SET_NSC1_CODEC);
+ //BUG nshc2 codec is registered with same subtype as Conntrack codec
registrator.registerActionDeserializer(SetNshc2Codec.DESERIALIZER_KEY, NiciraActionCodecs.SET_NSC2_CODEC);
registrator.registerActionSerializer(SetNshc2Codec.SERIALIZER_KEY, NiciraActionCodecs.SET_NSC2_CODEC);
+ //Continue
registrator.registerActionDeserializer(SetNshc3Codec.DESERIALIZER_KEY, NiciraActionCodecs.SET_NSC3_CODEC);
registrator.registerActionSerializer(SetNshc3Codec.SERIALIZER_KEY, NiciraActionCodecs.SET_NSC3_CODEC);
registrator.registerActionDeserializer(SetNshc4Codec.DESERIALIZER_KEY, NiciraActionCodecs.SET_NSC4_CODEC);
registrator.registerActionSerializer(SetNshc4Codec.SERIALIZER_KEY, NiciraActionCodecs.SET_NSC4_CODEC);
registrator.registerActionDeserializer(SetNsiCodec.DESERIALIZER_KEY, NiciraActionCodecs.SET_NSI_CODEC);
registrator.registerActionSerializer(SetNsiCodec.SERIALIZER_KEY, NiciraActionCodecs.SET_NSI_CODEC);
+ //BUG Conntrack codec is registered with same subtype as Nshc2 codec
registrator.registerActionSerializer(ConntrackCodec.SERIALIZER_KEY, NiciraActionCodecs.CONNTRACK_CODEC);
registrator.registerActionDeserializer(ConntrackCodec.DESERIALIZER_KEY, NiciraActionCodecs.CONNTRACK_CODEC);
+ //Continue
+
registrator.registerMatchEntrySerializer(Reg0Codec.SERIALIZER_KEY, NiciraMatchCodecs.REG0_CODEC);
registrator.registerMatchEntryDeserializer(Reg0Codec.DESERIALIZER_KEY, NiciraMatchCodecs.REG0_CODEC);
registrator.unregisterActionSerializer(SetNsiCodec.SERIALIZER_KEY);
registrator.unregisterActionDeserializer(SetNspCodec.DESERIALIZER_KEY);
registrator.unregisterActionSerializer(SetNspCodec.SERIALIZER_KEY);
+ //Added this line (unregisterDeserialize was missing)
+ registrator.unregisterActionDeserializer(SetNshc1Codec.DESERIALIZER_KEY);
registrator.unregisterActionSerializer(SetNshc1Codec.SERIALIZER_KEY);
registrator.unregisterActionDeserializer(SetNshc2Codec.DESERIALIZER_KEY);
registrator.unregisterActionSerializer(SetNshc2Codec.SERIALIZER_KEY);
registrator.unregisterActionSerializer(SetNshc3Codec.SERIALIZER_KEY);
registrator.unregisterActionDeserializer(SetNshc4Codec.DESERIALIZER_KEY);
registrator.unregisterActionSerializer(SetNshc4Codec.SERIALIZER_KEY);
+ //BUG unregistering with same subtype as Nshc2
registrator.unregisterActionSerializer(ConntrackCodec.SERIALIZER_KEY);
registrator.unregisterActionDeserializer(ConntrackCodec.DESERIALIZER_KEY);
-
+ //CONTINUE
registrator.unregisterMatchEntrySerializer(Reg0Codec.SERIALIZER_KEY);
registrator.unregisterMatchEntryDeserializer(Reg0Codec.DESERIALIZER_KEY);
registrator.unregisterMatchEntrySerializer(Reg1Codec.SERIALIZER_KEY);
serializeHeader(input, outBuffer);
TcpDstCaseValue tcpDstCase = ((TcpDstCaseValue) input.getMatchEntryValue());
outBuffer.writeShort(tcpDstCase.getTcpDstValues().getPort().getValue());
- outBuffer.writeShort(tcpDstCase.getTcpDstValues().getMask());
}
@Override
public MatchEntry deserialize(ByteBuf message) {
MatchEntryBuilder matchEntryBuilder = deserializeHeader(message);
- matchEntryBuilder.setHasMask(true);
int portNo = message.readUnsignedShort();
- int mask = message.readUnsignedShort();
- message.readBytes(mask);
TcpDstCaseValueBuilder caseBuilder = new TcpDstCaseValueBuilder();
TcpDstValuesBuilder tcpDstValuesBuilder = new TcpDstValuesBuilder();
tcpDstValuesBuilder.setPort(new PortNumber(portNo));
- tcpDstValuesBuilder.setMask(portNo);
caseBuilder.setTcpDstValues(tcpDstValuesBuilder.build());
matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
return matchEntryBuilder.build();
}
@Override
- public Class<? extends MatchField> getNxmField() {
- return NxmOfTcpDst.class;
- }
+ public Class<? extends MatchField> getNxmField() { return NxmOfTcpDst.class; }
@Override
public Class<? extends OxmClassBase> getOxmClass() {
serializeHeader(input, outBuffer);
TcpSrcCaseValue tcpSrcCase = ((TcpSrcCaseValue) input.getMatchEntryValue());
outBuffer.writeShort(tcpSrcCase.getTcpSrcValues().getPort().getValue());
- outBuffer.writeShort(tcpSrcCase.getTcpSrcValues().getMask());
}
@Override
public MatchEntry deserialize(ByteBuf message) {
MatchEntryBuilder matchEntryBuilder = deserializeHeader(message);
- matchEntryBuilder.setHasMask(true);
+ matchEntryBuilder.setHasMask(false);
int portNo = message.readUnsignedShort();
- int mask = message.readUnsignedShort();
- message.readBytes(mask);
TcpSrcCaseValueBuilder caseBuilder = new TcpSrcCaseValueBuilder();
TcpSrcValuesBuilder tcpSrcValuesBuilder = new TcpSrcValuesBuilder();
tcpSrcValuesBuilder.setPort(new PortNumber(portNo));
- tcpSrcValuesBuilder.setMask(portNo);
caseBuilder.setTcpSrcValues(tcpSrcValuesBuilder.build());
matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
return matchEntryBuilder.build();
serializeHeader(input, outBuffer);
UdpDstCaseValue udpDstCase = ((UdpDstCaseValue) input.getMatchEntryValue());
outBuffer.writeShort(udpDstCase.getUdpDstValues().getPort().getValue());
- outBuffer.writeShort(udpDstCase.getUdpDstValues().getMask());
}
@Override
public MatchEntry deserialize(ByteBuf message) {
MatchEntryBuilder matchEntryBuilder = deserializeHeader(message);
- matchEntryBuilder.setHasMask(true);
+ matchEntryBuilder.setHasMask(false);
int portNo = message.readUnsignedShort();
- int mask = message.readUnsignedShort();
- message.readBytes(mask);
UdpDstCaseValueBuilder caseBuilder = new UdpDstCaseValueBuilder();
UdpDstValuesBuilder udpDstValuesBuilder = new UdpDstValuesBuilder();
udpDstValuesBuilder.setPort(new PortNumber(portNo));
- udpDstValuesBuilder.setMask(portNo);
caseBuilder.setUdpDstValues(udpDstValuesBuilder.build());
matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
return matchEntryBuilder.build();
serializeHeader(input, outBuffer);
UdpSrcCaseValue udpSrcCase = ((UdpSrcCaseValue) input.getMatchEntryValue());
outBuffer.writeShort(udpSrcCase.getUdpSrcValues().getPort().getValue());
- outBuffer.writeShort(udpSrcCase.getUdpSrcValues().getMask());
}
@Override
public MatchEntry deserialize(ByteBuf message) {
MatchEntryBuilder matchEntryBuilder = deserializeHeader(message);
- matchEntryBuilder.setHasMask(true);
+ matchEntryBuilder.setHasMask(false);
int portNo = message.readUnsignedShort();
- int mask = message.readUnsignedShort();
- message.readBytes(mask);
UdpSrcCaseValueBuilder caseBuilder = new UdpSrcCaseValueBuilder();
UdpSrcValuesBuilder udpSrcValuesBuilder = new UdpSrcValuesBuilder();
udpSrcValuesBuilder.setPort(new PortNumber(portNo));
- udpSrcValuesBuilder.setMask(portNo);
caseBuilder.setUdpSrcValues(udpSrcValuesBuilder.build());
matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
return matchEntryBuilder.build();
--- /dev/null
+/**
+ * Copyright (c) 2016 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.openflowjava.nx;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowjava.nx.api.NiciraActionDeserializerKey;
+import org.opendaylight.openflowjava.nx.api.NiciraActionSerializerKey;
+import org.opendaylight.openflowjava.nx.api.NiciraExtensionCodecRegistrator;
+import org.opendaylight.openflowjava.nx.codec.action.MultipathCodec;
+import org.opendaylight.openflowjava.nx.codec.action.OutputRegCodec;
+import org.opendaylight.openflowjava.nx.codec.action.RegLoadCodec;
+import org.opendaylight.openflowjava.nx.codec.action.RegMoveCodec;
+import org.opendaylight.openflowjava.nx.codec.action.ResubmitCodec;
+import org.opendaylight.openflowjava.nx.codec.action.SetNshc1Codec;
+import org.opendaylight.openflowjava.nx.codec.action.SetNshc3Codec;
+import org.opendaylight.openflowjava.nx.codec.action.SetNshc4Codec;
+import org.opendaylight.openflowjava.nx.codec.action.SetNsiCodec;
+import org.opendaylight.openflowjava.nx.codec.action.SetNspCodec;
+import org.opendaylight.openflowjava.nx.codec.match.ArpOpCodec;
+import org.opendaylight.openflowjava.nx.codec.match.ArpShaCodec;
+import org.opendaylight.openflowjava.nx.codec.match.ArpSpaCodec;
+import org.opendaylight.openflowjava.nx.codec.match.ArpThaCodec;
+import org.opendaylight.openflowjava.nx.codec.match.ArpTpaCodec;
+import org.opendaylight.openflowjava.nx.codec.match.CtStateCodec;
+import org.opendaylight.openflowjava.nx.codec.match.CtZoneCodec;
+import org.opendaylight.openflowjava.nx.codec.match.EthDstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.EthSrcCodec;
+import org.opendaylight.openflowjava.nx.codec.match.EthTypeCodec;
+import org.opendaylight.openflowjava.nx.codec.match.Nshc1Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Nshc2Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Nshc3Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Nshc4Codec;
+import org.opendaylight.openflowjava.nx.codec.match.NsiCodec;
+import org.opendaylight.openflowjava.nx.codec.match.NspCodec;
+import org.opendaylight.openflowjava.nx.codec.match.Reg0Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Reg1Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Reg2Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Reg3Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Reg4Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Reg5Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Reg6Codec;
+import org.opendaylight.openflowjava.nx.codec.match.Reg7Codec;
+import org.opendaylight.openflowjava.nx.codec.match.TcpDstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.TcpSrcCodec;
+import org.opendaylight.openflowjava.nx.codec.match.TunIdCodec;
+import org.opendaylight.openflowjava.nx.codec.match.TunIpv4DstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.TunIpv4SrcCodec;
+import org.opendaylight.openflowjava.nx.codec.match.UdpDstCodec;
+import org.opendaylight.openflowjava.nx.codec.match.UdpSrcCodec;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntryDeserializerKey;
+import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm0Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Nxm1Class;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionConntrack;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionMultipath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionOutputReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionRegLoad;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionRegMove;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionResubmit;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionSetNshc1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionSetNshc3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionSetNshc4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionSetNsi;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionSetNsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxArpSha;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxArpTha;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxCtState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxCtZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxNshc1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxNshc2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxNshc3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxNshc4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxNsi;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxNsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxTunId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxTunIpv4Dst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxTunIpv4Src;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfArpOp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfArpSpa;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfArpTpa;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfEthDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfEthSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfEthType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfTcpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfTcpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfUdpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfUdpSrc;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NiciraExtensionsRegistratorTest {
+
+ NiciraExtensionsRegistrator niciraExtensionsRegistrator;
+
+ @Mock
+ NiciraExtensionCodecRegistrator registrator;
+
+ @Before
+ public void setUp() {
+ niciraExtensionsRegistrator = new NiciraExtensionsRegistrator(registrator);
+ }
+
+ @Test
+ public void registerNiciraExtensionsTest() {
+ niciraExtensionsRegistrator.registerNiciraExtensions();
+
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 7)), Matchers.any(RegLoadCodec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionRegLoad.class)), Matchers.any(RegLoadCodec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 6)), Matchers.any(RegMoveCodec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionRegMove.class)), Matchers.any(RegMoveCodec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 15)), Matchers.any(OutputRegCodec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionOutputReg.class)), Matchers.any(OutputRegCodec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionResubmit.class)), Matchers.any(ResubmitCodec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 1)), Matchers.any(ResubmitCodec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 14)), Matchers.any(ResubmitCodec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionMultipath.class)), Matchers.any(MultipathCodec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 10)), Matchers.any(MultipathCodec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 32)), Matchers.any(SetNspCodec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNsp.class)), Matchers.any(SetNspCodec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 34)), Matchers.any(SetNshc1Codec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNshc1.class)), Matchers.any(SetNshc1Codec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 36)), Matchers.any(SetNshc3Codec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNshc3.class)), Matchers.any(SetNshc3Codec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 37)), Matchers.any(SetNshc4Codec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNshc4.class)), Matchers.any(SetNshc4Codec.class));
+ Mockito.verify(registrator).registerActionDeserializer(Matchers.eq(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 33)), Matchers.any(SetNsiCodec.class));
+ Mockito.verify(registrator).registerActionSerializer(Matchers.eq(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNsi.class)), Matchers.any(SetNsiCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg0.class)), Matchers.any(Reg0Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 0)), Matchers.any(Reg0Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg1.class)), Matchers.any(Reg1Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 1)), Matchers.any(Reg1Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg2.class)), Matchers.any(Reg2Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 2)), Matchers.any(Reg2Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg3.class)), Matchers.any(Reg3Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 3)), Matchers.any(Reg3Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg4.class)), Matchers.any(Reg4Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 4)), Matchers.any(Reg4Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg5.class)), Matchers.any(Reg5Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 5)), Matchers.any(Reg5Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg6.class)), Matchers.any(Reg6Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 6)), Matchers.any(Reg6Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg7.class)), Matchers.any(Reg7Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 7)), Matchers.any(Reg7Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxTunId.class)), Matchers.any(TunIdCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 16)), Matchers.any(TunIdCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfArpOp.class)), Matchers.any(ArpOpCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 15)), Matchers.any(ArpOpCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxArpSha.class)), Matchers.any(ArpShaCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 17)), Matchers.any(ArpShaCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfArpSpa.class)), Matchers.any(ArpSpaCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 16)), Matchers.any(ArpSpaCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxArpTha.class)), Matchers.any(ArpThaCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 18)), Matchers.any(ArpThaCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfArpTpa.class)), Matchers.any(ArpTpaCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 17)), Matchers.any(ArpTpaCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfEthDst.class)), Matchers.any(EthDstCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 1)), Matchers.any(EthDstCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfEthSrc.class)), Matchers.any(EthSrcCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 2)), Matchers.any(EthSrcCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfEthType.class)), Matchers.any(EthTypeCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 3)), Matchers.any(EthTypeCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNsp.class)), Matchers.any(NspCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 37)), Matchers.any(NspCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNshc1.class)), Matchers.any(Nshc1Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 39)), Matchers.any(Nshc1Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNshc2.class)), Matchers.any(Nshc2Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 40)), Matchers.any(Nshc2Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNshc3.class)), Matchers.any(Nshc3Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 41)), Matchers.any(Nshc3Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNshc4.class)), Matchers.any(Nshc4Codec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 42)), Matchers.any(Nshc4Codec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNsi.class)), Matchers.any(NsiCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 38)), Matchers.any(NsiCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxTunIpv4Dst.class)), Matchers.any(TunIpv4DstCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 32)), Matchers.any(TunIpv4DstCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxTunIpv4Src.class)), Matchers.any(TunIpv4SrcCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 31)), Matchers.any(TunIpv4SrcCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfTcpSrc.class)), Matchers.any(TcpSrcCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 9)), Matchers.any(TcpSrcCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfTcpDst.class)), Matchers.any(TcpDstCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 10)), Matchers.any(TcpDstCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfUdpSrc.class)), Matchers.any(UdpSrcCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 11)), Matchers.any(UdpSrcCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfUdpDst.class)), Matchers.any(UdpDstCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 12)), Matchers.any(UdpDstCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxCtState.class)), Matchers.any(CtStateCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 105)), Matchers.any(CtStateCodec.class));
+ Mockito.verify(registrator).registerMatchEntrySerializer(Matchers.eq(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxCtZone.class)), Matchers.any(CtZoneCodec.class));
+ Mockito.verify(registrator).registerMatchEntryDeserializer(Matchers.eq(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 106)), Matchers.any(CtZoneCodec.class));
+ }
+
+ @Test
+ public void unregisterExtensionsTest() {
+ niciraExtensionsRegistrator.unregisterExtensions();
+
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 7));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionRegLoad.class));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 6));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionRegMove.class));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 15));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionOutputReg.class));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 1));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 14));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionResubmit.class));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 10));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionMultipath.class));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 33));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNsi.class));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 32));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNsp.class));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 34));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNshc1.class));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 36));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNshc3.class));
+ Mockito.verify(registrator).unregisterActionDeserializer(new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, 37));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionSetNshc4.class));
+ Mockito.verify(registrator).unregisterActionSerializer(new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionConntrack.class));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg0.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 0));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg1.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 1));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg2.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 2));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg3.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 3));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg4.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 4));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg5.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 5));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg6.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 6));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxReg7.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 7));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxTunId.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 16));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfArpOp.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 15));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxArpSha.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 17));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfArpSpa.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 16));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxArpTha.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 18));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfArpTpa.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 17));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfEthDst.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 1));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfEthSrc.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 2));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfEthType.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 3));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNsp.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 37));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNsi.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 38));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNshc1.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 39));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNshc2.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 40));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNshc3.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 41));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxNshc4.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 42));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxTunIpv4Dst.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 32));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxTunIpv4Src.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 31));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfTcpSrc.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 9));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfTcpDst.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 10));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfUdpSrc.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 11));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm0Class.class, NxmOfUdpDst.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_0_CLASS, 12));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxCtState.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 105));
+ Mockito.verify(registrator).unregisterMatchEntrySerializer(new MatchEntrySerializerKey<>(EncodeConstants.OF13_VERSION_ID, Nxm1Class.class, NxmNxCtZone.class));
+ Mockito.verify(registrator).unregisterMatchEntryDeserializer(new MatchEntryDeserializerKey(EncodeConstants.OF13_VERSION_ID, OxmMatchConstants.NXM_1_CLASS, 106));
+ }
+}
*/
package org.opendaylight.openflowplugin.extension.vendor.nicira.convertor;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import java.util.List;
+import java.util.ListIterator;
+
/**
* @author msunal
*
public final class IpConverter {
public static long Ipv4AddressToLong(Ipv4Address ipv4Address) {
- String ipAddress = ipv4Address.getValue();
- long result = 0;
- String[] atoms = ipAddress.split("\\.");
- for (int i = 3; i >= 0; i--) {
- result |= (Long.parseLong(atoms[3 - i]) << (i * 8));
+ long result = 0 ;
+ Iterable<String> splitted = Splitter.on('.')
+ .trimResults()
+ .omitEmptyStrings()
+ .split(ipv4Address.getValue());
+
+ List<String> splittedAddress = Lists.newArrayList(splitted.iterator());
+ int maxIndex = splittedAddress.size() - 1;
+ ListIterator<String> listIter = splittedAddress.listIterator();
+ while(listIter.hasNext()) {
+ String current = listIter.next();
+ int i = splittedAddress.indexOf(current);
+ result |= (Long.parseLong(current) << ((maxIndex-i) * 8));
}
return result & 0xFFFFFFFF;
}
--- /dev/null
+package org.opendaylight.openflowplugin.extension.vendor.nicira.convertor;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+
+public class IpConverterTest {
+
+ @Test
+ public void testIpv4AddressToLong() {
+ Ipv4Address ipAddress = new Ipv4Address("192.168.1.2");
+ long address = 0xc0a80102L;
+ assertEquals(address, IpConverter.Ipv4AddressToLong(ipAddress));
+ }
+
+ @Test
+ public void testIpv4AddressToLong2() {
+ Ipv4Address ipAddress = new Ipv4Address("10.168.1.2");
+ long address = 0x0aa80102L;
+ assertEquals(address, IpConverter.Ipv4AddressToLong(ipAddress));
+ }
+
+}
-package org.opendaylight.openflowplugin.extension.vendor.nicira.convertor.match;
+package org.opendaylight.openflowplugin.extension.vendor.nicira.convertor;
import static org.junit.Assert.assertEquals;
<module>openflowplugin-extension-api</module>
<module>openflowplugin-extension-nicira</module>
<module>openflowplugin-extension-nicira-config</module>
+ <module>features-he</module>
<module>features</module>
- <module>features-li</module>
<module>test-extension</module>
</modules>
</project>
</parent>
<groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>features-openflowplugin-li</artifactId>
+ <artifactId>features-openflowplugin-he</artifactId>
<packaging>jar</packaging>
<version>0.3.0-SNAPSHOT</version>
<openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
<dlux.version>0.4.0-SNAPSHOT</dlux.version>
<lldp.version>0.11.0-SNAPSHOT</lldp.version>
-
<config.configfile.directory>etc/opendaylight/karaf</config.configfile.directory>
- <config.statistics.manager.configfile>30-statistics-manager.xml</config.statistics.manager.configfile>
<restconf.version>1.4.0-SNAPSHOT</restconf.version>
<mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
</properties>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>forwardingrules-manager</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>forwardingrules-manager-config</artifactId>
- <classifier>config</classifier>
- <type>xml</type>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>inventory-manager</artifactId>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>statistics-manager</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>statistics-manager-config</artifactId>
- <classifier>config</classifier>
- <type>xml</type>
- </dependency>
<dependency>
<groupId>org.opendaylight.dlux</groupId>
<artifactId>openflowplugin-impl</artifactId>
</dependency>
<dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>table-miss-enforcer</artifactId>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-blueprint-config-he</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>table-miss-enforcer</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>topology-lldp-discovery</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>topology-lldp-discovery</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>topology-manager</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>topology-manager</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>of-switch-config-pusher</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>of-switch-config-pusher</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>lldp-speaker</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
<artifactId>drop-test-karaf</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>drop-test-karaf</artifactId>
- <classifier>config</classifier>
- <type>xml</type>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
<artifactId>test-common</artifactId>
<groupId>org.opendaylight.openflowplugin</groupId>
<artifactId>openflowplugin-controller-config</artifactId>
<type>xml</type>
- <classifier>config-Li</classifier>
+ <classifier>config-He</classifier>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
<type>xml</type>
<classifier>config</classifier>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>old-notification-supplier</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>old-notification-supplier</artifactId>
- </dependency>
</dependencies>
</project>
~ and is available at http://www.eclipse.org/legal/epl-v10.html
-->
-<features name="openflowplugin-li-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+<features name="openflowplugin-he-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
<repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
<repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
<repository>mvn:org.opendaylight.openflowjava/features-openflowjava/${openflowjava.version}/xml/features</repository>
<repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
<repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features</repository>
-
- <feature name='odl-openflowplugin-all-li' description="OpenDaylight :: Openflow Plugin :: All" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-southbound-li</feature>
- <feature version="${project.version}">odl-openflowplugin-flow-services-li</feature>
- <feature version="${project.version}">odl-openflowplugin-flow-services-rest-li</feature>
- <feature version="${project.version}">odl-openflowplugin-flow-services-ui-li</feature>
+ <feature name='odl-openflowplugin-all-he' description="OpenDaylight :: Openflow Plugin :: All" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-southbound-he</feature>
+ <feature version="${project.version}">odl-openflowplugin-flow-services-he</feature>
+ <feature version="${project.version}">odl-openflowplugin-flow-services-rest-he</feature>
+ <feature version="${project.version}">odl-openflowplugin-flow-services-ui-he</feature>
</feature>
- <feature name='odl-openflowplugin-southbound-li' description="OpenDaylight :: Openflow Plugin :: Li southBound API implementation " version='${project.version}'>
+ <feature name='odl-openflowplugin-southbound-he' description="OpenDaylight :: Openflow Plugin :: SouthBound" version='${project.version}'>
<feature version="${mdsal.version}">odl-mdsal-broker</feature>
- <feature version="${project.version}">odl-openflowplugin-nsf-services-li</feature>
+ <feature version="${project.version}">odl-openflowplugin-nsf-model-he</feature>
<feature version="${openflowjava.version}">odl-openflowjava-protocol</feature>
<bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-common/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-api/{{VERSION}}</bundle>
- <!-- TODO : remove dependency on openflowplugin in the future -->
<bundle>mvn:org.opendaylight.openflowplugin/openflowplugin/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-api/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-extension-api/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/42-openflowplugin-Li.xml">mvn:org.opendaylight.openflowplugin/openflowplugin-controller-config/{{VERSION}}/xml/config-Li</configfile>
+ <bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.openflowplugin.applications/inventory-manager/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.openflowplugin.applications/statistics-manager/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-blueprint-config-he/{{VERSION}}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/42-openflowplugin-He.xml">mvn:org.opendaylight.openflowplugin/openflowplugin-controller-config/{{VERSION}}/xml/config-He</configfile>
+ <configfile finalname="etc/opendaylight/karaf/43-msg-spy.xml">mvn:org.opendaylight.openflowplugin/openflowplugin-controller-config/{{VERSION}}/xml/configmsgspy</configfile>
</feature>
- <feature name='odl-openflowplugin-flow-services-li' description="OpenDaylight :: Openflow Plugin :: Flow Services" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-southbound-li</feature>
- <feature version="${project.version}">odl-openflowplugin-app-config-pusher-li</feature>
- <feature version="${project.version}">odl-openflowplugin-app-lldp-speaker-li</feature>
- <feature version="${project.version}">odl-openflowplugin-nsf-services-li</feature>
-
+ <feature name='odl-openflowplugin-flow-services-he' description="OpenDaylight :: Openflow Plugin :: Flow Services" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-southbound-he</feature>
+ <feature version="${project.version}">odl-openflowplugin-app-config-pusher-he</feature>
+ <feature version="${project.version}">odl-openflowplugin-app-lldp-speaker-he</feature>
+ <feature version="${project.version}">odl-openflowplugin-nsf-services-he</feature>
</feature>
- <feature name='odl-openflowplugin-nsf-services-li' version='${project.version}'
- description="OpenDaylight :: OpenflowPlugin :: NSF :: Services">
+ <feature name='odl-openflowplugin-nsf-services-he' version='${project.version}'
+ description="OpenDaylight :: OpenflowPlugin :: NSF :: Services">
<feature version='${mdsal.version}'>odl-mdsal-broker</feature>
- <feature version='${project.version}'>odl-openflowplugin-nsf-model-li</feature>
+ <feature version='${project.version}'>odl-openflowplugin-nsf-model-he</feature>
<bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-common/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.applications/topology-manager/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.applications/topology-lldp-discovery/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.applications/forwardingrules-manager/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/30-forwardingrules-manager.xml">mvn:org.opendaylight.openflowplugin.applications/forwardingrules-manager-config/{{VERSION}}/xml/config</configfile>
- <configfile finalname="etc/opendaylight/karaf/72-topology-lldp-discovery.xml">mvn:org.opendaylight.openflowplugin.applications/topology-lldp-discovery/{{VERSION}}/xml/config</configfile>
- <configfile finalname="etc/opendaylight/karaf/73-topology-manager.xml">mvn:org.opendaylight.openflowplugin.applications/topology-manager/{{VERSION}}/xml/config</configfile>
+ <bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
</feature>
- <feature name='odl-openflowplugin-nsf-model-li' version='${project.version}'
- description="OpenDaylight :: OpenflowPlugin :: NSF :: Model">
+ <feature name='odl-openflowplugin-nsf-model-he' version='${project.version}'
+ description="OpenDaylight :: OpenflowPlugin :: NSF :: Model">
<!-- general models -->
<feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
<bundle>mvn:org.opendaylight.controller.model/model-inventory/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.model/model-flow-service/{{VERSION}}</bundle>
</feature>
- <feature name='odl-openflowplugin-flow-services-rest-li' description="OpenDaylight :: Openflow Plugin :: Flow Services :: REST" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-flow-services-li</feature>
+ <feature name='odl-openflowplugin-flow-services-rest-he' description="OpenDaylight :: Openflow Plugin :: Flow Services :: REST" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-flow-services-he</feature>
<feature version="${restconf.version}">odl-restconf</feature>
</feature>
- <feature name='odl-openflowplugin-flow-services-ui-li' description="OpenDaylight :: Openflow Plugin :: Flow Services :: UI" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-flow-services-rest-li</feature>
+ <feature name='odl-openflowplugin-flow-services-ui-he' description="OpenDaylight :: Openflow Plugin :: Flow Services :: UI" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-flow-services-rest-he</feature>
<feature version="${dlux.version}">odl-dlux-core</feature>
<feature version="${restconf.version}">odl-mdsal-apidocs</feature>
<feature version="${mdsal.version}">odl-mdsal-xsql</feature>
</feature>
<!-- CBENCH TESTING -->
- <feature name='odl-openflowplugin-drop-test-li' description="OpenDaylight :: Openflow Plugin :: Drop Test" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-flow-services-li</feature>
+ <feature name='odl-openflowplugin-drop-test-he' description="OpenDaylight :: Openflow Plugin :: Drop Test" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-flow-services-he</feature>
<bundle>mvn:org.opendaylight.openflowplugin/test-common/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin/drop-test-karaf/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/69-drop-test.xml">mvn:org.opendaylight.openflowplugin/drop-test-karaf/{{VERSION}}/xml/config</configfile>
</feature>
<!-- APPLICATIONS -->
- <feature name='odl-openflowplugin-app-table-miss-enforcer-li' description="OpenDaylight :: Openflow Plugin :: Application - table-miss-enforcer" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-southbound-li</feature>
+ <feature name='odl-openflowplugin-app-table-miss-enforcer-he' description="OpenDaylight :: Openflow Plugin :: Application - table-miss-enforcer" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-southbound-he</feature>
<bundle>mvn:org.opendaylight.openflowplugin.applications/table-miss-enforcer/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/69-table-miss-enforcer.xml">mvn:org.opendaylight.openflowplugin.applications/table-miss-enforcer/{{VERSION}}/xml/config</configfile>
</feature>
- <feature name='odl-openflowplugin-app-config-pusher-li' description="OpenDaylight :: Openflow Plugin :: app - default config-pusher" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-southbound-li</feature>
+ <feature name='odl-openflowplugin-app-config-pusher-he' description="OpenDaylight :: Openflow Plugin :: app - default config-pusher" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-southbound-he</feature>
<bundle>mvn:org.opendaylight.openflowplugin.applications/of-switch-config-pusher/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/70-of-switch-config-pusher.xml">mvn:org.opendaylight.openflowplugin.applications/of-switch-config-pusher/{{VERSION}}/xml/config</configfile>
</feature>
- <feature name='odl-openflowplugin-app-lldp-speaker-li' description="OpenDaylight :: Openflow Plugin :: app lldp-speaker" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-southbound-li</feature>
+ <feature name='odl-openflowplugin-app-lldp-speaker-he' description="OpenDaylight :: Openflow Plugin :: app lldp-speaker" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-southbound-he</feature>
+ <bundle>mvn:org.opendaylight.openflowplugin.applications/topology-lldp-discovery/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.applications/lldp-speaker/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/71-lldp-speaker.xml">mvn:org.opendaylight.openflowplugin.applications/lldp-speaker/{{VERSION}}/xml/config</configfile>
- <configfile finalname="etc/opendaylight/karaf/72-topology-lldp-discovery.xml">mvn:org.opendaylight.openflowplugin.applications/topology-lldp-discovery/{{VERSION}}/xml/config</configfile>
- </feature>
-
- <feature name='odl-openflowplugin-app-bulk-o-matic-li' description="OpenDaylight :: Openflow Plugin :: app bulk flow operations support" version='${project.version}'>
- <feature version="${project.version}">odl-openflowplugin-southbound-li</feature>
- <bundle>mvn:org.opendaylight.openflowplugin.applications/bulk-o-matic/${project.version}</bundle>
- <configfile finalname="etc/opendaylight/karaf/71-bulk-o-matic.xml">mvn:org.opendaylight.openflowplugin.applications/bulk-o-matic/${project.version}/xml/config</configfile>
</feature>
- <feature name='odl-openflowplugin-old-notifications-li' description="OpenDaylight :: Openflow Plugin :: app old notifications supplier" version='${project.version}'>
- <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
- <feature version="${project.version}">odl-openflowplugin-nsf-model-li</feature>
- <bundle>mvn:org.opendaylight.openflowplugin.applications/old-notification-supplier/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/73-old-notification-supplier.xml">mvn:org.opendaylight.openflowplugin.applications/old-notification-supplier/{{VERSION}}/xml/config</configfile>
+ <feature name='odl-openflowplugin-app-bulk-o-matic-he' description="OpenDaylight :: Openflow Plugin :: app bulk flow operations support" version='${project.version}'>
+ <feature version="${project.version}">odl-openflowplugin-southbound-he</feature>
+ <bundle>mvn:org.opendaylight.openflowplugin.applications/bulk-o-matic/{{VERSION}}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/71-bulk-o-matic.xml">mvn:org.opendaylight.openflowplugin.applications/bulk-o-matic/{{VERSION}}/xml/config</configfile>
</feature>
</features>
<openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
<dlux.version>0.4.0-SNAPSHOT</dlux.version>
<lldp.version>0.11.0-SNAPSHOT</lldp.version>
-
<config.configfile.directory>etc/opendaylight/karaf</config.configfile.directory>
- <config.statistics.manager.configfile>30-statistics-manager.xml</config.statistics.manager.configfile>
- <config.inventory.manager.configfile>40-inventory-manager.xml</config.inventory.manager.configfile>
<restconf.version>1.4.0-SNAPSHOT</restconf.version>
<mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
</properties>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>forwardingrules-manager-config</artifactId>
- <classifier>config</classifier>
- <type>xml</type>
+ <artifactId>forwardingrules-sync</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>inventory-manager</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>inventory-manager</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>lldp-speaker</artifactId>
<artifactId>statistics-manager</artifactId>
</dependency>
<dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>statistics-manager-config</artifactId>
- <classifier>config</classifier>
- <type>xml</type>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-blueprint-config</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>table-miss-enforcer</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>table-miss-enforcer</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>topology-lldp-discovery</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>topology-lldp-discovery</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
+
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>topology-manager</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>topology-manager</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin.applications</groupId>
<artifactId>of-switch-config-pusher</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>of-switch-config-pusher</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>lldp-speaker</artifactId>
- <type>xml</type>
- <classifier>config</classifier>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
<artifactId>drop-test-karaf</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>drop-test-karaf</artifactId>
- <classifier>config</classifier>
- <type>xml</type>
- </dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
<artifactId>test-common</artifactId>
<groupId>org.opendaylight.openflowplugin</groupId>
<artifactId>openflowplugin-controller-config</artifactId>
<type>xml</type>
- <classifier>config-He</classifier>
+ <classifier>config-Li</classifier>
</dependency>
<dependency>
<groupId>org.opendaylight.openflowplugin</groupId>
<type>xml</type>
<classifier>config</classifier>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.applications</groupId>
+ <artifactId>notification-supplier</artifactId>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.applications</groupId>
+ <artifactId>notification-supplier</artifactId>
+ </dependency>
</dependencies>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <tag>HEAD</tag>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
- </scm>
</project>
-->
<features name="openflowplugin-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
<repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
<repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
<repository>mvn:org.opendaylight.openflowjava/features-openflowjava/${openflowjava.version}/xml/features</repository>
<repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
<repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features</repository>
+
<feature name='odl-openflowplugin-all' description="OpenDaylight :: Openflow Plugin :: All" version='${project.version}'>
<feature version="${project.version}">odl-openflowplugin-southbound</feature>
<feature version="${project.version}">odl-openflowplugin-flow-services</feature>
<feature version="${project.version}">odl-openflowplugin-flow-services-ui</feature>
</feature>
- <feature name='odl-openflowplugin-southbound' description="OpenDaylight :: Openflow Plugin :: SouthBound" version='${project.version}'>
+ <feature name='odl-openflowplugin-southbound' description="OpenDaylight :: Openflow Plugin :: Li southBound API implementation " version='${project.version}'>
<feature version="${mdsal.version}">odl-mdsal-broker</feature>
- <feature version="${project.version}">odl-openflowplugin-nsf-model</feature>
+ <feature version="${project.version}">odl-openflowplugin-nsf-services</feature>
<feature version="${openflowjava.version}">odl-openflowjava-protocol</feature>
<bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-common/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.openflowplugin/openflowplugin/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-api/{{VERSION}}</bundle>
+ <!-- TODO : remove dependency on openflowplugin in the future -->
+ <bundle>mvn:org.opendaylight.openflowplugin/openflowplugin/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-impl/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-extension-api/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.openflowplugin.applications/inventory-manager/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.openflowplugin.applications/statistics-manager/{{VERSION}}</bundle>
- <configfile finalname="${config.configfile.directory}/${config.statistics.manager.configfile}">mvn:org.opendaylight.openflowplugin.applications/statistics-manager-config/{{VERSION}}/xml/config</configfile>
- <configfile finalname="${config.configfile.directory}/${config.inventory.manager.configfile}">mvn:org.opendaylight.openflowplugin.applications/inventory-manager/{{VERSION}}/xml/config</configfile>
- <configfile finalname="etc/opendaylight/karaf/42-openflowplugin-He.xml">mvn:org.opendaylight.openflowplugin/openflowplugin-controller-config/{{VERSION}}/xml/config-He</configfile>
- <configfile finalname="etc/opendaylight/karaf/43-msg-spy.xml">mvn:org.opendaylight.openflowplugin/openflowplugin-controller-config/{{VERSION}}/xml/configmsgspy</configfile>
+ <bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-blueprint-config/{{VERSION}}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/42-openflowplugin-Li.xml">mvn:org.opendaylight.openflowplugin/openflowplugin-controller-config/{{VERSION}}/xml/config-Li</configfile>
</feature>
<feature name='odl-openflowplugin-flow-services' description="OpenDaylight :: Openflow Plugin :: Flow Services" version='${project.version}'>
<feature version="${project.version}">odl-openflowplugin-app-config-pusher</feature>
<feature version="${project.version}">odl-openflowplugin-app-lldp-speaker</feature>
<feature version="${project.version}">odl-openflowplugin-nsf-services</feature>
+
</feature>
<feature name='odl-openflowplugin-nsf-services' version='${project.version}'
- description="OpenDaylight :: OpenflowPlugin :: NSF :: Services">
+ description="OpenDaylight :: OpenflowPlugin :: NSF :: Services">
<feature version='${mdsal.version}'>odl-mdsal-broker</feature>
<feature version='${project.version}'>odl-openflowplugin-nsf-model</feature>
<bundle>mvn:org.opendaylight.openflowplugin/openflowplugin-common/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.applications/topology-manager/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.applications/topology-lldp-discovery/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.applications/forwardingrules-manager/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/30-forwardingrules-manager.xml">mvn:org.opendaylight.openflowplugin.applications/forwardingrules-manager-config/{{VERSION}}/xml/config</configfile>
- <configfile finalname="etc/opendaylight/karaf/72-topology-lldp-discovery.xml">mvn:org.opendaylight.openflowplugin.applications/topology-lldp-discovery/{{VERSION}}/xml/config</configfile>
- <configfile finalname="etc/opendaylight/karaf/73-topology-manager.xml">mvn:org.opendaylight.openflowplugin.applications/topology-manager/{{VERSION}}/xml/config</configfile>
+ <bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
</feature>
<feature name='odl-openflowplugin-nsf-model' version='${project.version}'
- description="OpenDaylight :: OpenflowPlugin :: NSF :: Model">
+ description="OpenDaylight :: OpenflowPlugin :: NSF :: Model">
<!-- general models -->
<feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
<bundle>mvn:org.opendaylight.controller.model/model-inventory/{{VERSION}}</bundle>
<feature version="${project.version}">odl-openflowplugin-flow-services</feature>
<bundle>mvn:org.opendaylight.openflowplugin/test-common/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin/drop-test-karaf/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/69-drop-test.xml">mvn:org.opendaylight.openflowplugin/drop-test-karaf/{{VERSION}}/xml/config</configfile>
</feature>
<!-- APPLICATIONS -->
<feature name='odl-openflowplugin-app-table-miss-enforcer' description="OpenDaylight :: Openflow Plugin :: Application - table-miss-enforcer" version='${project.version}'>
<feature version="${project.version}">odl-openflowplugin-southbound</feature>
<bundle>mvn:org.opendaylight.openflowplugin.applications/table-miss-enforcer/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/69-table-miss-enforcer.xml">mvn:org.opendaylight.openflowplugin.applications/table-miss-enforcer/{{VERSION}}/xml/config</configfile>
</feature>
<feature name='odl-openflowplugin-app-config-pusher' description="OpenDaylight :: Openflow Plugin :: app - default config-pusher" version='${project.version}'>
<feature version="${project.version}">odl-openflowplugin-southbound</feature>
<bundle>mvn:org.opendaylight.openflowplugin.applications/of-switch-config-pusher/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/70-of-switch-config-pusher.xml">mvn:org.opendaylight.openflowplugin.applications/of-switch-config-pusher/{{VERSION}}/xml/config</configfile>
</feature>
<feature name='odl-openflowplugin-app-lldp-speaker' description="OpenDaylight :: Openflow Plugin :: app lldp-speaker" version='${project.version}'>
<feature version="${project.version}">odl-openflowplugin-southbound</feature>
- <bundle>mvn:org.opendaylight.openflowplugin.applications/topology-lldp-discovery/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.applications/lldp-speaker/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/71-lldp-speaker.xml">mvn:org.opendaylight.openflowplugin.applications/lldp-speaker/{{VERSION}}/xml/config</configfile>
- <configfile finalname="etc/opendaylight/karaf/72-topology-lldp-discovery.xml">mvn:org.opendaylight.openflowplugin.applications/topology-lldp-discovery/{{VERSION}}/xml/config</configfile>
</feature>
<feature name='odl-openflowplugin-app-bulk-o-matic' description="OpenDaylight :: Openflow Plugin :: app bulk flow operations support" version='${project.version}'>
<feature version="${project.version}">odl-openflowplugin-southbound</feature>
- <bundle>mvn:org.opendaylight.openflowplugin.applications/bulk-o-matic/{{VERSION}}</bundle>
- <configfile finalname="etc/opendaylight/karaf/71-bulk-o-matic.xml">mvn:org.opendaylight.openflowplugin.applications/bulk-o-matic/{{VERSION}}/xml/config</configfile>
+ <bundle>mvn:org.opendaylight.openflowplugin.applications/bulk-o-matic/${project.version}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/71-bulk-o-matic.xml">mvn:org.opendaylight.openflowplugin.applications/bulk-o-matic/${project.version}/xml/config</configfile>
+ </feature>
+
+ <feature name='odl-openflowplugin-notifications' description="OpenDaylight :: Openflow Plugin :: app notifications supplier" version='${project.version}'>
+ <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+ <feature version="${project.version}">odl-openflowplugin-nsf-model</feature>
+ <bundle>mvn:org.opendaylight.openflowplugin.applications/notification-supplier/{{VERSION}}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/73-notification-supplier.xml">mvn:org.opendaylight.openflowplugin.applications/notification-supplier/{{VERSION}}/xml/config</configfile>
</feature>
</features>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.api.openflow;
+
+/**
+ * General API for all OFP Context
+ */
+public interface OFPContext {
+
+ /**
+ * distinguished device context states
+ */
+ enum CONTEXT_STATE {
+ /**
+ * initial phase
+ */
+ INITIALIZATION,
+ /**
+ * standard phase
+ */
+ WORKING,
+ /**
+ * termination phase
+ */
+ TERMINATION
+ }
+
+ CONTEXT_STATE getState();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.api.openflow;
+
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+
+/**
+ * Generic API for all managers
+ */
+public interface OFPManager {
+
+ <T extends OFPContext> T gainContext(final DeviceInfo deviceInfo);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.openflowplugin.api.openflow;
+
+import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
+
+/**
+ * Factory for creating OpenFlowPluginProvider instances.
+ *
+ * @author Thomas Pantelis
+ */
+public interface OpenFlowPluginProviderFactory {
+ OpenFlowPluginProvider newInstance(OpenflowProviderConfig providerConfig, DataBroker dataBroker,
+ RpcProviderRegistry rpcRegistry, NotificationService notificationService,
+ NotificationPublishService notificationPublishService,
+ EntityOwnershipService entityOwnershipService,
+ List<SwitchConnectionProvider> switchConnectionProviders);
+}
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
* Each OpenFlow session is tracked by a Connection Context. These attach to a particular Device Context in such a way,
* that there is at most one primary session associated with a Device Context.
* </p>
- * Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
*/
public interface ConnectionContext {
* change internal state to {@link ConnectionContext.CONNECTION_STATE#WORKING}
*/
void changeStateToWorking();
+
+ /**
+ * Create and return basic device info
+ * @return
+ */
+ DeviceInfo getDeviceInfo();
+
+ /**
+ * This method creates a basic device information. Should be called after nodeId and features are set in connection context
+ */
+ void handshakeSuccessful();
}
import io.netty.util.Timeout;
import java.math.BigInteger;
import java.util.List;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceReplyProcessor;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
-import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
-import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
-import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
-import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
/**
* <p>
* Context can have at any point in time. Should this quota be exceeded, any further attempt to make
* a request to the switch will fail immediately, with proper error indication.
* </p>
- * Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
*/
public interface DeviceContext extends AutoCloseable,
DeviceReplyProcessor,
- PortNumberCache,
TxFacade,
- XidSequencer {
-
- void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled);
-
- /**
- * distinguished device context states
- */
- enum DEVICE_CONTEXT_STATE {
- /**
- * initial phase of talking to switch
- */
- INITIALIZATION,
- /**
- * standard phase - interacting with switch
- */
- WORKING,
- /**
- * termination phase of talking to switch
- */
- TERMINATION
- }
-
- /**
- * Method returns current device context state.
- *
- * @return {@link DeviceContext.DEVICE_CONTEXT_STATE}
- */
- DEVICE_CONTEXT_STATE getDeviceContextState();
+ XidSequencer,
+ OFPContext,
+ DeviceRegistry{
/**
* Method close all auxiliary connections and primary connection.
*/
DeviceState getDeviceState();
- /**
- * Method has to activate (MASTER) or deactivate (SLAVE) TransactionChainManager.
- * TransactionChainManager represents possibility to write or delete Node subtree data
- * for actual Controller Cluster Node. We are able to have an active TxManager only if
- * newRole is {@link OfpRole#BECOMESLAVE}.
- * Parameters are used as marker to be sure it is change to SLAVE from MASTER or from
- * MASTER to SLAVE and the last parameter "cleanDataStore" is used for validation only.
- * @param oldRole - old role for quick validation for needed processing
- * @param role - NewRole expect to be {@link OfpRole#BECOMESLAVE} or {@link OfpRole#BECOMEMASTER}
- * @return RoleChangeTxChainManager future for activation/deactivation
- * @deprecated replaced by method onDeviceTakeClusterLeadership and onDevicLostClusterLeadership
- */
- @Deprecated
- ListenableFuture<Void> onClusterRoleChange(@Nullable OfpRole oldRole, @CheckForNull OfpRole role);
-
- /**
- * Method has to activate TransactionChainManager and prepare all Contexts from Device Contects suite
- * to Taking ClusterLeadership role {@link OfpRole#BECOMEMASTER} (e.g. Routed RPC registration, StatPolling ...)
- * @return DeviceInitialization furure
- */
- ListenableFuture<Void> onDeviceTakeClusterLeadership();
-
- /**
- * Method has to deactivate TransactionChainManager and prepare all Contexts from Device Contects suite
- * to Lost ClusterLeadership role {@link OfpRole#BECOMESLAVE} (e.g. Stop RPC rounting, stop StatPolling ...)
- * @return RoleChangeTxChainManager future for deactivation
- */
- ListenableFuture<Void> onDeviceLostClusterLeadership();
+ DeviceInfo getDeviceInfo();
/**
* Method has to close TxManager ASAP we are notified about Closed Connection
*/
ConnectionContext getAuxiliaryConnectiobContexts(BigInteger cookie);
- /**
- * Method exposes flow registry used for storing flow ids identified by calculated flow hash.
- *
- * @return
- */
- DeviceFlowRegistry getDeviceFlowRegistry();
-
- /**
- * Method exposes device group registry used for storing group ids.
- *
- * @return
- */
- DeviceGroupRegistry getDeviceGroupRegistry();
-
- /**
- * Method exposes device meter registry used for storing meter ids.
- *
- * @return
- */
- DeviceMeterRegistry getDeviceMeterRegistry();
-
/**
* @return translator library
*/
ItemLifeCycleRegistry getItemLifeCycleSourceRegistry();
- void setRpcContext(RpcContext rpcContext);
-
- RpcContext getRpcContext();
-
- void setStatisticsContext(StatisticsContext statisticsContext);
-
- StatisticsContext getStatisticsContext();
-
@Override
void close();
}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.api.openflow.device;
+
+import java.math.BigInteger;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * API defining basic device information
+ */
+public interface DeviceInfo {
+
+ /**
+ * @return id of encapsulated node
+ */
+ NodeId getNodeId();
+
+ /**
+ * @return {@link Node} instance identifier
+ */
+ KeyedInstanceIdentifier<Node, NodeKey> getNodeInstanceIdentifier();
+
+ /**
+ * @return version
+ */
+ Short getVersion();
+
+ /**
+ * @return datapathId
+ */
+ BigInteger getDatapathId();
+
+}
package org.opendaylight.openflowplugin.api.openflow.device;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
-import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.openflowplugin.api.openflow.OFPManager;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceConnectedHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.translator.TranslatorLibrarian;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
/**
* This interface is responsible for instantiating DeviceContext and
* registering transaction chain for each DeviceContext. Each device
* has its own device context managed by this manager.
- * Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
*/
public interface DeviceManager extends DeviceConnectedHandler, DeviceDisconnectedHandler, DeviceLifecycleSupervisor,
- DeviceInitializationPhaseHandler, DeviceTerminationPhaseHandler, TranslatorLibrarian, AutoCloseable {
+ DeviceInitializationPhaseHandler, DeviceTerminationPhaseHandler, TranslatorLibrarian, AutoCloseable, OFPManager {
+
/**
- * Sets notification publish service
+ * invoked after all services injected
+ */
+ void initialize();
+
+ /**
+ * Method has to activate (MASTER) or deactivate (SLAVE) TransactionChainManager.
+ * TransactionChainManager represents possibility to write or delete Node subtree data
+ * for actual Controller Cluster Node. We are able to have an active TxManager only if
+ * newRole is {@link OfpRole#BECOMESLAVE}.
+ * Parameters are used as marker to be sure it is change to SLAVE from MASTER or from
+ * MASTER to SLAVE and the last parameter "cleanDataStore" is used for validation only.
*
- * @param notificationPublishService
+ * @param deviceInfo which device
+ * @param role - NewRole expect to be {@link OfpRole#BECOMESLAVE} or {@link OfpRole#BECOMEMASTER}
+ * @return RoleChangeTxChainManager future for activation/deactivation
*/
- void setNotificationPublishService(NotificationPublishService notificationPublishService);
+ ListenableFuture<Void> onClusterRoleChange(final DeviceInfo deviceInfo, final OfpRole role);
/**
- * invoked after all services injected
+ * Register device synchronize listeners
+ * @param deviceSynchronizeListener are notified if device is synchronized or not
*/
- void initialize();
+ void addDeviceSynchronizeListener(final DeviceSynchronizeListener deviceSynchronizeListener);
+
+ /**
+ * Notify all registered listeners about synchronized status
+ * @param deviceInfo which device
+ * @param deviceSynchronized true if device is synchronized
+ */
+ void notifyDeviceSynchronizeListeners(final DeviceInfo deviceInfo, final boolean deviceSynchronized);
+
+ /**
+ * Register device valid listeners
+ * @param deviceValidListener are notified if device is valid or not
+ */
+ void addDeviceValidListener(final DeviceValidListener deviceValidListener);
/**
- * Returning device context from map maintained in device manager
- * This prevent to send whole device context to another context
- * If device context not exists for nodeId it will return null
- * @param nodeId
- * @return device context or null
+ * Notify all registered listeners about valid status
+ * @param deviceInfo which device
+ * @param deviceValid true if device is valid
*/
- DeviceContext getDeviceContextFromNodeId(NodeId nodeId);
+ void notifyDeviceValidListeners(final DeviceInfo deviceInfo, final boolean deviceValid);
- void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled);
}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.api.openflow.device;
+
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
+import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
+import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
+
+/**
+ * Flows, Groups and Meter registry
+ */
+public interface DeviceRegistry {
+
+ /**
+ * Method exposes flow registry used for storing flow ids identified by calculated flow hash.
+ *
+ * @return
+ */
+ DeviceFlowRegistry getDeviceFlowRegistry();
+
+ /**
+ * Method exposes device group registry used for storing group ids.
+ *
+ * @return
+ */
+ DeviceGroupRegistry getDeviceGroupRegistry();
+
+ /**
+ * Method exposes device meter registry used for storing meter ids.
+ *
+ * @return
+ */
+ DeviceMeterRegistry getDeviceMeterRegistry();
+
+}
package org.opendaylight.openflowplugin.api.openflow.device;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-
/**
- * Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
+ * Holder of device's structure
*/
-public interface DeviceState {
-
- /**
- * @return id of encapsulated node
- */
- NodeId getNodeId();
-
- /**
- * @return {@link Node} instance identifier
- */
- KeyedInstanceIdentifier<Node, NodeKey> getNodeInstanceIdentifier();
-
- /**
- * @return the features of corresponding switch
- */
- GetFeaturesOutput getFeatures();
+public interface DeviceState extends DeviceSynchronizeListener, DeviceValidListener {
/**
* @return true if this session is valid
*/
boolean isValid();
- /**
- * @param valid the valid to set
- */
- void setValid(boolean valid);
-
- /**
- * Return node current OF protocol version
- *
- * @return
- */
- short getVersion();
-
/**
* Return true if we have relevant meter information
* from device
void setQueueStatisticsAvailable(boolean available);
- void setDeviceSynchronized(boolean deviceSynchronized);
-
boolean isStatisticsPollingEnabled();
void setStatisticsPollingEnabledProp(boolean statPollEnabled);
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.api.openflow.device;
+
+/**
+ * API for device synchronized listeners
+ */
+public interface DeviceSynchronizeListener {
+
+ void deviceIsSynchronized(final DeviceInfo deviceInfo, final boolean isSynchronized);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.openflowplugin.api.openflow.device;
+
+/**
+ * API for device synchronized listeners
+ */
+public interface DeviceValidListener {
+
+ void deviceIsValid(final DeviceInfo deviceInfo, final boolean isValid);
+
+}
/**
* Translates from input to output
* @param input
- * @param deviceState
+ * @param deviceInfo
* @param connectionDistinguisher
* @return message of output type
*/
- O translate(I input, DeviceState deviceState, Object connectionDistinguisher);
+ O translate(I input, DeviceInfo deviceInfo, Object connectionDistinguisher);
}
+++ /dev/null
-/*
- * Copyright (c) 2015 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.openflowplugin.api.openflow.device;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-
-/**
- * keeps mapping between port number (protocol based) and {@link NodeConnectorRef}
- */
-public interface PortNumberCache {
-
- /**
- * @param portNumber
- * @return corresponding nodeConnectorRef if present
- */
- @Nullable
- @Deprecated
- NodeConnectorRef lookupNodeConnectorRef(Long portNumber);
-
- /**
- * @param portNumber protocol port number
- * @param nodeConnectorRef corresponding value of {@link NodeConnectorRef}
- */
- @Deprecated
- void storeNodeConnectorRef(@Nonnull Long portNumber, @Nonnull NodeConnectorRef nodeConnectorRef);
-}
import javax.annotation.CheckForNull;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
/**
* openflowplugin-api
/**
* Method represents an initialization cycle for {@link DeviceContext} preparation for use.
*
- * @param nodeId
+ * @param deviceInfo
* @throws Exception - needs to be catch in ConnectionHandler implementation
*/
- void onDeviceContextLevelUp(@CheckForNull NodeId nodeId) throws Exception;
+ void onDeviceContextLevelUp(@CheckForNull DeviceInfo deviceInfo) throws Exception;
}
import javax.annotation.CheckForNull;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
/**
* Interface represent handler for dead device connection annihilating cycle.
/**
* Method represents a termination cycle for {@link DeviceContext}.
*
- * @param deviceContext - {@link DeviceContext}
+ * @param deviceInfo - {@link DeviceInfo}
*/
- void onDeviceContextLevelDown(@CheckForNull DeviceContext deviceContext);
+ void onDeviceContextLevelDown(@CheckForNull DeviceInfo deviceInfo);
}
package org.opendaylight.openflowplugin.api.openflow.lifecycle;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
/**
* This API is for all listeners who wish to know about device context in cluster
/**
* Notification about start phase in device context, right after successful handshake
- * @param nodeId
+ * @param deviceInfo
* @param success or failure
*/
- void deviceStartInitializationDone(final NodeId nodeId, final boolean success);
+ void deviceStartInitializationDone(final DeviceInfo deviceInfo, final boolean success);
/**
* Notification about start phase in device context, after all other contexts initialized properly
- * @param nodeId
+ * @param deviceInfo
* @param success
*/
- void deviceInitializationDone(final NodeId nodeId, final boolean success);
+ void deviceInitializationDone(final DeviceInfo deviceInfo, final boolean success);
}
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.openflowplugin.api.openflow.OFPManager;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
-import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-
-import javax.annotation.Nonnull;
-import java.util.concurrent.TimeUnit;
/**
* This class is a binder between all managers
/**
* Returns device context from device manager device contexts maps
- * @param nodeId node identification
- * @return null if context doesn't exists
+ *
+ * @param deviceInfo@return null if context doesn't exists
+ */
+ DeviceContext getDeviceContext(DeviceInfo deviceInfo);
+
+
+ /**
+ * Setter for device manager once set it cant be unset or overwritten
+ * @param manager
*/
- DeviceContext getDeviceContext(final NodeId nodeId);
+ void setSafelyManager(OFPManager manager);
/**
* Registers ont time listener for notify when services rpc, statistics are done stop or start
* @param manager service change listener
- * @param nodeId node identification
+ * @param deviceInfo node identification
*/
- void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final NodeId nodeId);
+ void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final DeviceInfo deviceInfo);
/**
- * Returns device of version
- * @param nodeId node identification
- * @return null if device context doesn't exists
+ * Returns statistics context from statistics managers contexts maps
+ *
+ * @param deviceInfo@return null if context doesn't exists
*/
- Short gainVersionSafely(final NodeId nodeId);
+ StatisticsContext getStatisticsContext(DeviceInfo deviceInfo);
/**
* Set new timeout for {@link io.netty.util.HashedWheelTimer}
/**
* Interrupt connection for the node
- * @param nodeId node identification
+ * @param deviceInfo node identification
*/
- void closeConnection(final NodeId nodeId);
+ void closeConnection(final DeviceInfo deviceInfo);
- /**
- * Setter for device manager once set it cant be unset or overwritten
- * @param deviceManager should be set in OpenFlowPluginProviderImpl
- */
- void setSafelyDeviceManager(final DeviceManager deviceManager);
-
- /**
- * Setter for statistics manager once set it cant be unset or overwritten
- * @param statisticsManager should be set in OpenFlowPluginProviderImpl
- */
- void setSafelyStatisticsManager(final StatisticsManager statisticsManager);
+ ConnectionContext.CONNECTION_STATE gainConnectionStateSafely(DeviceInfo deviceInfo);
/**
* Xid from outboundqueue
- * @param nodeId
+ * @param deviceInfo
* @return
*/
- Long reserveXidForDeviceMessage(final NodeId nodeId);
+ Long reserveXidForDeviceMessage(final DeviceInfo deviceInfo);
+
+ NotificationPublishService getNotificationPublishService();
+
+ void setNotificationPublishService(NotificationPublishService notificationPublishService);
}
package org.opendaylight.openflowplugin.api.openflow.lifecycle;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
/**
/**
* Notification when initialization for role context is done
- * @param nodeId
+ * @param deviceInfo
* @param success or failure
*/
- void roleInitializationDone(final NodeId nodeId, final boolean success);
+ void roleInitializationDone(final DeviceInfo deviceInfo, final boolean success);
/**
* Notification when the role change on device is done
- * @param nodeId
+ * @param deviceInfo
* @param success
* @param newRole
* @param initializationPhase
*/
- void roleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole newRole, final boolean initializationPhase);
+ void roleChangeOnDevice(final DeviceInfo deviceInfo, final boolean success, final OfpRole newRole, final boolean initializationPhase);
}
package org.opendaylight.openflowplugin.api.openflow.lifecycle;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
/**
* This API is defined for listening when services (Statistics and RPCs) are fully stopped
/**
* Notification when services (rpc, statistics) are started or stopped working
- * @param nodeId
+ * @param deviceInfo
* @param success
*/
- void servicesChangeDone(NodeId nodeId, boolean success);
+ void servicesChangeDone(DeviceInfo deviceInfo, boolean success);
}
--- /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.openflowplugin.api.openflow.md;
+
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+
+public abstract class AbstractModelDrivenSwitchRegistration extends AbstractObjectRegistration<ModelDrivenSwitch>
+ implements ModelDrivenSwitchRegistration {
+
+ protected AbstractModelDrivenSwitchRegistration(final ModelDrivenSwitch instance) {
+ super(instance);
+ }
+
+}
package org.opendaylight.openflowplugin.api.openflow.md;
import com.google.common.base.Optional;
+import java.math.BigInteger;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import java.math.BigInteger;
-
/**
* interface concatenating all md-sal services provided by OF-switch
*/
* @param rpcProviderRegistry
* @return wrapped list of {service provider + path} registration couples
*/
- CompositeObjectRegistration<ModelDrivenSwitch> register(RpcProviderRegistry rpcProviderRegistry);
+ ModelDrivenSwitchRegistration register(RpcProviderRegistry rpcProviderRegistry);
/**
* @return id of encapsulated node (served by this impl)
--- /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.openflowplugin.api.openflow.md;
+
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+
+public interface ModelDrivenSwitchRegistration extends ObjectRegistration<ModelDrivenSwitch> {
+ @Override
+ void close();
+}
package org.opendaylight.openflowplugin.api.openflow.md.core;
+import com.google.common.collect.Lists;
import java.util.List;
import java.util.concurrent.Future;
-
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
import org.opendaylight.openflowplugin.api.openflow.md.queue.QueueProcessor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yangtools.yang.binding.DataObject;
-import com.google.common.collect.Lists;
-
/**
* @author mirehak
*/
package org.opendaylight.openflowplugin.api.openflow.md.core;
+import com.google.common.base.Preconditions;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.Notification;
-import com.google.common.base.Preconditions;
-
/**
*
*/
package org.opendaylight.openflowplugin.api.openflow.md.core.session;
import java.util.concurrent.Future;
-
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetConfigInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
import org.opendaylight.yangtools.yang.common.RpcResult;
/**
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitchRegistration;
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationEnqueuer;
import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationQueueWrapper;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
/**
* @author mirehak
/**
* @param registration provider composite registration
*/
- void setProviderRegistration(CompositeObjectRegistration<ModelDrivenSwitch> registration);
+ void setProviderRegistration(ModelDrivenSwitchRegistration registration);
/**
* @return provider composite registration
*/
- CompositeObjectRegistration<ModelDrivenSwitch> getProviderRegistration();
+ ModelDrivenSwitchRegistration getProviderRegistration();
/**
* @return seed value for random operations
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
-import org.opendaylight.openflowplugin.api.openflow.statistics.MessageSpy;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
import org.opendaylight.openflowplugin.api.openflow.md.queue.PopListener;
+import org.opendaylight.openflowplugin.api.openflow.statistics.MessageSpy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import java.util.Collection;
import java.util.List;
import java.util.Map;
-
import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
*/
package org.opendaylight.openflowplugin.api.openflow.md.util;
+import com.google.common.collect.Iterators;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
-import com.google.common.collect.Iterators;
-
/**
* Zipper groups together a list of queues and exposes one poll method. Polling iterates through
* all groups and returns first not-null result of poll method on each queue. If after polling each
*/
package org.opendaylight.openflowplugin.api.openflow.role;
+import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
-import javax.annotation.Nonnull;
-
/**
- * Rewrote whole role context to prevent errors to change role on cluster
+ * Role context for change role on cluster
*/
-public interface RoleContext extends RequestContextStack, AutoCloseable {
+public interface RoleContext extends RequestContextStack, AutoCloseable, OFPContext {
/**
* Initialization method is responsible for a registration of
* Actual nodeId
* @return
*/
- NodeId getNodeId();
+ DeviceInfo getDeviceInfo();
/**
* Returns true if main entity is registered
*/
package org.opendaylight.openflowplugin.api.openflow.role;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.OFPManager;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
/**
* Created by kramesha on 8/31/15.
*/
public interface RoleManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler, AutoCloseable,
- DeviceTerminationPhaseHandler {
+ DeviceTerminationPhaseHandler, OFPManager {
String ENTITY_TYPE = "openflow";
String TX_ENTITY_TYPE = "ofTransaction";
*/
package org.opendaylight.openflowplugin.api.openflow.rpc;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.yangtools.yang.binding.RpcService;
* tracks the state of any user requests and how they map onto protocol requests. It uses
* {@link org.opendaylight.openflowplugin.api.openflow.device.RequestContext} to perform requests.
* <p>
- * Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
*/
-public interface RpcContext extends RequestContextStack, AutoCloseable {
+public interface RpcContext extends RequestContextStack, AutoCloseable, OFPContext {
<S extends RpcService> void registerRpcServiceImplementation(Class<S> serviceClass, S serviceInstance);
<S extends RpcService> S lookupRpcService(Class<S> serviceClass);
@Override
void close();
+
+ void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled);
+
+ boolean isStatisticsRpcEnabled();
}
package org.opendaylight.openflowplugin.api.openflow.rpc;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.openflowplugin.api.openflow.OFPManager;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
/**
* The RPC Manager will maintain an RPC Context for each online switch. RPC context for device is created when
- * {@link org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler#onDeviceContextLevelUp(NodeId)}
+ * {@link org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler#onDeviceContextLevelUp(org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo)}
* is called.
* <p>
* Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
*/
-public interface RpcManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler, AutoCloseable, DeviceTerminationPhaseHandler {
+public interface RpcManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler, AutoCloseable, DeviceTerminationPhaseHandler, OFPManager {
+ void setStatisticsRpcEnabled(boolean statisticsRpcEnabled);
}
package org.opendaylight.openflowplugin.api.openflow.statistics;
-import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
import io.netty.util.Timeout;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import java.util.Optional;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
/**
- * Created by Martin Bobak <mbobak@cisco.com> on 27.2.2015.
+ * Context for statistics
*/
-public interface StatisticsContext extends RequestContextStack, AutoCloseable {
+public interface StatisticsContext extends RequestContextStack, AutoCloseable, OFPContext {
+ /**
+ * Gather data from device
+ * @return true if gathering was successful
+ */
ListenableFuture<Boolean> gatherDynamicData();
+ /**
+ * Initial data gathering
+ * @return true if gathering was successful
+ */
+ ListenableFuture<Boolean> initialGatherDynamicData();
+
/**
* Method has to be called from DeviceInitialization Method, otherwise
* we are not able to poll anything. Statistics Context normally initialize
*/
ItemLifecycleListener getItemLifeCycleListener();
- /**
- * Statistics Context has to be able to return own DeviceCtx
- * @return {@link DeviceContext}
- */
- DeviceContext getDeviceContext();
-
@Override
void close();
package org.opendaylight.openflowplugin.api.openflow.statistics;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.OFPManager;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
/**
- * Created by Martin Bobak <mbobak@cisco.com> on 26.2.2015.
+ * Manager to start or stop scheduling statistics
*/
public interface StatisticsManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler,
- DeviceTerminationPhaseHandler, AutoCloseable {
+ DeviceTerminationPhaseHandler, AutoCloseable, OFPManager {
- void startScheduling(NodeId nodeId);
- void stopScheduling(NodeId nodeId);
+ void startScheduling(DeviceInfo deviceInfo);
+ void stopScheduling(DeviceInfo deviceInfo);
@Override
void close();
--- /dev/null
+module openflow-provider-config {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:openflow:provider:config";
+ prefix "openflow-provider-config";
+
+ description
+ "Configuration for an Openflow provider.";
+
+ revision "2016-05-10" {
+ description
+ "Initial revision";
+ }
+
+ typedef non-zero-uint32-type {
+ type uint32 {
+ range "1..max";
+ }
+ }
+
+ typedef non-zero-uint16-type {
+ type uint16 {
+ range "1..max";
+ }
+ }
+
+ container openflow-provider-config {
+ leaf rpc-requests-quota {
+ type uint32;
+ default 20000;
+ }
+
+ leaf switch-features-mandatory {
+ type boolean;
+ default false;
+ }
+
+ leaf global-notification-quota {
+ type uint32;
+ default 64000;
+ }
+
+ leaf is-statistics-polling-off {
+ type boolean;
+ default "false";
+ }
+
+ leaf is-statistics-rpc-enabled {
+ description "Deprecated - exposing backward compatible statistics rpcs providing result in form of async notification";
+ type boolean;
+ default "false";
+ }
+
+ leaf barrier-interval-timeout-limit {
+ type non-zero-uint32-type;
+ default 500;
+ }
+
+ leaf barrier-count-limit {
+ type non-zero-uint16-type;
+ default 25600;
+ }
+
+ leaf echo-reply-timeout {
+ type non-zero-uint32-type;
+ default 2000;
+ }
+
+ leaf thread-pool-min-threads {
+ description "Mininum (starting) number of threads in thread pool";
+ type uint16;
+ default 1;
+ }
+
+ leaf thread-pool-max-threads {
+ description "Maximum number of threads in thread pool";
+ type non-zero-uint16-type;
+ default 32000;
+ }
+
+ leaf thread-pool-timeout {
+ description "After how much time (in seconds) of inactivity will be threads in pool terminated";
+ type uint32;
+ default 60;
+ }
+ }
+}
\ No newline at end of file
identity openflow-provider{
base config:service-type;
config:java-class "org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider";
+ config:disable-osgi-service-registration;
+ status deprecated;
}
}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+
+ <artifactId>openflowplugin-blueprint-config-he</artifactId>
+ <description>Blueprint configuration for the Helium openflowplugin</description>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <DynamicImport-Package>*</DynamicImport-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" odl:type="pingpong"/>
+ <reference id="rpcRegistry" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"/>
+ <reference id="notificationService" interface="org.opendaylight.controller.sal.binding.api.NotificationProviderService"/>
+ <reference id="entityOwnershipService" interface="org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService"/>
+
+ <!-- Create the StatisticsManager -->
+ <reference id="statsManagerFactory"
+ interface="org.opendaylight.openflowplugin.applications.statistics.manager.StatisticsManagerFactory"/>
+
+ <odl:clustered-app-config id="statsManagerAppConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.statistics.manager.config.rev160509.StatisticsManagerAppConfig"/>
+
+ <bean id="statsManager" factory-ref="statsManagerFactory" factory-method="newInstance">
+ <argument ref="statsManagerAppConfig"/>
+ <argument ref="dataBroker"/>
+ <argument ref="notificationService"/>
+ <argument ref="rpcRegistry"/>
+ <argument ref="entityOwnershipService"/>
+ </bean>
+
+ <!-- Create the Inventory manager/provider -->
+ <bean id="inventoryManager" class="org.opendaylight.openflowplugin.applications.inventory.manager.InventoryActivator"
+ init-method="start" destroy-method="close">
+ <argument ref="dataBroker"/>
+ <argument ref="notificationService"/>
+ <argument ref="entityOwnershipService"/>
+ </bean>
+
+ <reference id="switchConnProviderFactory"
+ interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProviderFactory"/>
+
+ <!-- Create OF switch connection provider on port 6633 -->
+ <odl:clustered-app-config id="defaultSwitchConnConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig"
+ list-key-value="openflow-switch-connection-provider-default-impl">
+ <odl:default-config><![CDATA[
+ <switch-connection-config xmlns="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:config">
+ <instance-name>openflow-switch-connection-provider-default-impl</instance-name>
+ <port>6633</port>
+ <transport-protocol>TCP</transport-protocol>
+ </switch-connection-config>
+ ]]></odl:default-config>
+ </odl:clustered-app-config>
+
+ <bean id="defaultSwitchConnProvider" factory-ref="switchConnProviderFactory" factory-method="newInstance">
+ <argument ref="defaultSwitchConnConfig"/>
+ </bean>
+
+ <service ref="defaultSwitchConnProvider" interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider"
+ odl:type="openflow-switch-connection-provider-default-impl"/>
+
+ <!-- Create OF switch connection provider on port 6653 -->
+ <odl:clustered-app-config id="legacySwitchConnConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig"
+ list-key-value="openflow-switch-connection-provider-legacy-impl">
+ <odl:default-config><![CDATA[
+ <switch-connection-config xmlns="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:config">
+ <instance-name>openflow-switch-connection-provider-legacy-impl</instance-name>
+ <port>6653</port>
+ <transport-protocol>TCP</transport-protocol>
+ </switch-connection-config>
+ ]]></odl:default-config>
+ </odl:clustered-app-config>
+
+ <bean id="legacySwitchConnProvider" factory-ref="switchConnProviderFactory" factory-method="newInstance">
+ <argument ref="legacySwitchConnConfig"/>
+ </bean>
+
+ <service ref="legacySwitchConnProvider" interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider"
+ odl:type="openflow-switch-connection-provider-legacy-impl"/>
+
+ <!-- Create OpenflowPluginProvider instance -->
+
+ <bean id="openflowPluginProvider" class="org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider"
+ init-method="initialization" destroy-method="close" depends-on="statsManager inventoryManager">
+ <property name="dataBroker" ref="dataBroker"/>
+ <property name="rpcRegistry" ref="rpcRegistry"/>
+ <property name="notificationService" ref="notificationService"/>
+ <property name="entityOwnershipService" ref="entityOwnershipService"/>
+ <property name="role" value="NOCHANGE"/>
+ <property name="skipTableFeatures" value="false" />
+ <property name="switchConnectionProviders">
+ <list>
+ <ref component-id="defaultSwitchConnProvider"/>
+ <ref component-id="legacySwitchConnProvider"/>
+ </list>
+ </property>
+ </bean>
+
+ <service ref="openflowPluginProvider" odl:type="openflow-provider-impl">
+ <interfaces>
+ <value>org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider</value>
+ <value>org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegistratorProvider</value>
+ </interfaces>
+ </service>
+
+</blueprint>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+
+ <artifactId>openflowplugin-blueprint-config</artifactId>
+ <description>Blueprint configuration for the openflowplugin</description>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <DynamicImport-Package>*</DynamicImport-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" odl:type="pingpong"/>
+ <reference id="rpcRegistry" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"/>
+ <reference id="notificationService" interface="org.opendaylight.controller.md.sal.binding.api.NotificationService"/>
+ <reference id="notificationPublishService" interface="org.opendaylight.controller.md.sal.binding.api.NotificationPublishService"/>
+ <reference id="entityOwnershipService" interface="org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService"/>
+
+ <reference id="switchConnProviderFactory"
+ interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProviderFactory"/>
+
+ <!-- Create OF switch connection provider on port 6633 -->
+ <odl:clustered-app-config id="defaultSwitchConnConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig"
+ list-key-value="openflow-switch-connection-provider-default-impl">
+ <odl:default-config><![CDATA[
+ <switch-connection-config xmlns="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:config">
+ <instance-name>openflow-switch-connection-provider-default-impl</instance-name>
+ <port>6633</port>
+ <transport-protocol>TCP</transport-protocol>
+ </switch-connection-config>
+ ]]></odl:default-config>
+ </odl:clustered-app-config>
+
+ <bean id="defaultSwitchConnProvider" factory-ref="switchConnProviderFactory" factory-method="newInstance">
+ <argument ref="defaultSwitchConnConfig"/>
+ </bean>
+
+ <service ref="defaultSwitchConnProvider" interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider"
+ odl:type="openflow-switch-connection-provider-default-impl"/>
+
+ <!-- Create OF switch connection provider on port 6653 -->
+ <odl:clustered-app-config id="legacySwitchConnConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.config.rev160506.SwitchConnectionConfig"
+ list-key-value="openflow-switch-connection-provider-legacy-impl">
+ <odl:default-config><![CDATA[
+ <switch-connection-config xmlns="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:config">
+ <instance-name>openflow-switch-connection-provider-legacy-impl</instance-name>
+ <port>6653</port>
+ <transport-protocol>TCP</transport-protocol>
+ </switch-connection-config>
+ ]]></odl:default-config>
+ </odl:clustered-app-config>
+
+ <bean id="legacySwitchConnProvider" factory-ref="switchConnProviderFactory" factory-method="newInstance">
+ <argument ref="legacySwitchConnConfig"/>
+ </bean>
+
+ <service ref="legacySwitchConnProvider" interface="org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider"
+ odl:type="openflow-switch-connection-provider-legacy-impl"/>
+
+ <!-- Create OpenflowPluginProvider instance -->
+
+ <odl:clustered-app-config id="openflowProviderConfig"
+ binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig"/>
+
+ <reference id="openflowPluginProviderFactory"
+ interface="org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProviderFactory"/>
+
+ <bean id="openflowPluginProvider" factory-ref="openflowPluginProviderFactory" factory-method="newInstance">
+ <argument ref="openflowProviderConfig"/>
+ <argument ref="dataBroker"/>
+ <argument ref="rpcRegistry"/>
+ <argument ref="notificationService"/>
+ <argument ref="notificationPublishService"/>
+ <argument ref="entityOwnershipService"/>
+ <argument>
+ <list>
+ <ref component-id="defaultSwitchConnProvider"/>
+ <ref component-id="legacySwitchConnProvider"/>
+ </list>
+ </argument>
+ </bean>
+
+ <service ref="openflowPluginProvider" odl:type="openflow-plugin-provider-impl">
+ <interfaces>
+ <value>org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider</value>
+ <value>org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegistratorProvider</value>
+ </interfaces>
+ </service>
+
+</blueprint>
\ No newline at end of file
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
+
+NOTE: This file is deprecated as wiring is now done via blueprint. This file is kept for
+ backwards compatibility. Runtime modifications are not honored.
-->
<snapshot>
<required-capabilities>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
<name>binding-notification-broker</name>
</notification-service>
- <ownership-service>
- <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
- <name>entity-ownership-service</name>
- </ownership-service>
-
+ <ownership-service>
+ <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
+ <name>entity-ownership-service</name>
+ </ownership-service>
+
+ <!-- openflowplugin configuraion -->
+ <skip-table-features>false</skip-table-features>
</module>
</modules>
import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.openflowplugin.api.openflow.OFPManager;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.DeviceContextChangeListener;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.ServiceChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
+import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
+import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderKeeper;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
+import org.opendaylight.openflowplugin.impl.util.MdSalRegistrationUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
-
/**
*/
-public final class LifecycleConductorImpl implements LifecycleConductor, RoleChangeListener, DeviceContextChangeListener {
+final class LifecycleConductorImpl implements LifecycleConductor, RoleChangeListener, DeviceContextChangeListener, ExtensionConverterProviderKeeper {
private static final Logger LOG = LoggerFactory.getLogger(LifecycleConductorImpl.class);
private static final int TICKS_PER_WHEEL = 500;
private static final long TICK_DURATION = 10; // 0.5 sec.
private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL);
+ private ExtensionConverterProvider extensionConverterProvider;
private DeviceManager deviceManager;
- private final MessageIntelligenceAgency messageIntelligenceAgency;
- private ConcurrentHashMap<NodeId, ServiceChangeListener> serviceChangeListeners = new ConcurrentHashMap<>();
private StatisticsManager statisticsManager;
+ private RpcManager rpcManager;
+ private final MessageIntelligenceAgency messageIntelligenceAgency;
+ private ConcurrentHashMap<DeviceInfo, ServiceChangeListener> serviceChangeListeners = new ConcurrentHashMap<>();
+ private NotificationPublishService notificationPublishService;
- public LifecycleConductorImpl(final MessageIntelligenceAgency messageIntelligenceAgency) {
- Preconditions.checkNotNull(messageIntelligenceAgency);
- this.messageIntelligenceAgency = messageIntelligenceAgency;
+ LifecycleConductorImpl(final MessageIntelligenceAgency messageIntelligenceAgency) {
+ this.messageIntelligenceAgency = Preconditions.checkNotNull(messageIntelligenceAgency);
}
- public void setSafelyDeviceManager(final DeviceManager deviceManager) {
- if (this.deviceManager == null) {
- this.deviceManager = deviceManager;
- }
+ @Override
+ public ExtensionConverterProvider getExtensionConverterProvider() {
+ return extensionConverterProvider;
}
- public void setSafelyStatisticsManager(final StatisticsManager statisticsManager) {
- if (this.statisticsManager == null) {
- this.statisticsManager = statisticsManager;
+ @Override
+ public void setExtensionConverterProvider(ExtensionConverterProvider extensionConverterProvider) {
+ this.extensionConverterProvider = extensionConverterProvider;
+ }
+
+ @Override
+ public void setSafelyManager(final OFPManager manager){
+ if (manager instanceof RpcManager) {
+ if (rpcManager != null) {
+ LOG.info("RPC manager {} is already defined in conductor. ", manager);
+ return;
+ }
+ this.rpcManager = (RpcManager) manager;
+ } else {
+ if (manager instanceof StatisticsManager) {
+ if (statisticsManager != null) {
+ LOG.info("Statistics manager {} is already defined in conductor. ", manager);
+ return;
+ }
+ this.statisticsManager = (StatisticsManager) manager;
+ } else {
+ if (manager instanceof DeviceManager) {
+ if (deviceManager != null) {
+ LOG.info("Device manager {} is already defined in conductor. ", manager);
+ return;
+ }
+ this.deviceManager = (DeviceManager) manager;
+ }
+ }
}
}
- public void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final NodeId nodeId){
- LOG.debug("Listener {} for service change for node {} registered.", manager, nodeId);
- serviceChangeListeners.put(nodeId, manager);
+ @Override
+ public void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final DeviceInfo deviceInfo){
+ LOG.debug("Listener {} for service change for node {} registered.", manager, deviceInfo.getNodeId());
+ serviceChangeListeners.put(deviceInfo, manager);
}
@VisibleForTesting
- void notifyServiceChangeListeners(final NodeId nodeId, final boolean success){
+ void notifyServiceChangeListeners(final DeviceInfo deviceInfo, final boolean success){
if (serviceChangeListeners.size() == 0) {
return;
}
LOG.debug("Notifying registered listeners for service change, no. of listeners {}", serviceChangeListeners.size());
- for (final Map.Entry<NodeId, ServiceChangeListener> nodeIdServiceChangeListenerEntry : serviceChangeListeners.entrySet()) {
- if (nodeIdServiceChangeListenerEntry.getKey().equals(nodeId)) {
- LOG.debug("Listener {} for service change for node {} was notified. Success was set on {}", nodeIdServiceChangeListenerEntry.getValue(), nodeId, success);
- nodeIdServiceChangeListenerEntry.getValue().servicesChangeDone(nodeId, success);
- serviceChangeListeners.remove(nodeId);
+ for (final Map.Entry<DeviceInfo, ServiceChangeListener> nodeIdServiceChangeListenerEntry : serviceChangeListeners.entrySet()) {
+ if (nodeIdServiceChangeListenerEntry.getKey().equals(deviceInfo)) {
+ LOG.debug("Listener {} for service change for node {} was notified. Success was set on {}", nodeIdServiceChangeListenerEntry.getValue(), deviceInfo, success);
+ nodeIdServiceChangeListenerEntry.getValue().servicesChangeDone(deviceInfo, success);
+ serviceChangeListeners.remove(deviceInfo);
}
}
}
@Override
- public void roleInitializationDone(final NodeId nodeId, final boolean success) {
+ public void roleInitializationDone(final DeviceInfo deviceInfo, final boolean success) {
if (!success) {
- LOG.warn("Initialization phase for node {} in role context was NOT successful, closing connection.", nodeId);
- closeConnection(nodeId);
+ LOG.warn("Initialization phase for node {} in role context was NOT successful, closing connection.", deviceInfo);
+ closeConnection(deviceInfo);
} else {
- LOG.info("initialization phase for node {} in role context was successful, continuing to next context.", nodeId);
+ LOG.info("initialization phase for node {} in role context was successful, continuing to next context.", deviceInfo);
}
}
- public void closeConnection(final NodeId nodeId) {
- LOG.debug("Close connection called for node {}", nodeId);
- final DeviceContext deviceContext = getDeviceContext(nodeId);
+ public void closeConnection(final DeviceInfo deviceInfo) {
+ LOG.debug("Close connection called for node {}", deviceInfo);
+ final DeviceContext deviceContext = getDeviceContext(deviceInfo);
if (null != deviceContext) {
+ deviceManager.notifyDeviceValidListeners(deviceInfo, false);
deviceContext.shutdownConnection();
}
}
@Override
- public void roleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
+ public void roleChangeOnDevice(final DeviceInfo deviceInfo, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
- final DeviceContext deviceContext = getDeviceContext(nodeId);
+ final DeviceContext deviceContext = getDeviceContext(deviceInfo);
if (null == deviceContext) {
LOG.warn("Something went wrong, device context for nodeId: {} doesn't exists");
return;
}
if (!success) {
- LOG.warn("Role change to {} in role context for node {} was NOT successful, closing connection", newRole, nodeId);
- closeConnection(nodeId);
+ LOG.warn("Role change to {} in role context for node {} was NOT successful, closing connection", newRole, deviceInfo);
+ closeConnection(deviceInfo);
} else {
if (initializationPhase) {
LOG.debug("Initialization phase skipping starting services.");
return;
}
- LOG.info("Role change to {} in role context for node {} was successful, starting/stopping services.", newRole, nodeId);
+ LOG.info("Role change to {} in role context for node {} was successful.", newRole, deviceInfo);
+
+ final String logText;
if (OfpRole.BECOMEMASTER.equals(newRole)) {
- statisticsManager.startScheduling(nodeId);
+ logText = "Start";
+ statisticsManager.startScheduling(deviceInfo);
+ MdSalRegistrationUtils.registerMasterServices(
+ rpcManager.gainContext(deviceInfo),
+ deviceContext,
+ OfpRole.BECOMEMASTER,
+ this.extensionConverterProvider);
+ if (((RpcContext)rpcManager.gainContext(deviceInfo)).isStatisticsRpcEnabled()) {
+ MdSalRegistrationUtils.registerStatCompatibilityServices(
+ rpcManager.gainContext(deviceInfo),
+ deviceManager.gainContext(deviceInfo),
+ notificationPublishService,
+ new AtomicLong());
+ }
} else {
- statisticsManager.stopScheduling(nodeId);
+ logText = "Stopp";
+ statisticsManager.stopScheduling(deviceInfo);
+ MdSalRegistrationUtils.registerSlaveServices(
+ rpcManager.gainContext(deviceInfo),
+ OfpRole.BECOMESLAVE);
}
- final ListenableFuture<Void> onClusterRoleChange = deviceContext.onClusterRoleChange(null, newRole);
+ final ListenableFuture<Void> onClusterRoleChange = deviceManager.onClusterRoleChange(deviceInfo, newRole);
Futures.addCallback(onClusterRoleChange, new FutureCallback<Void>() {
@Override
public void onSuccess(@Nullable final Void aVoid) {
- LOG.info("Starting/Stopping services for node {} was successful", nodeId);
- if (newRole.equals(OfpRole.BECOMESLAVE)) notifyServiceChangeListeners(nodeId, true);
+ LOG.info("{}ing services for node {} was successful", logText, deviceInfo);
+ if (newRole.equals(OfpRole.BECOMESLAVE)) notifyServiceChangeListeners(deviceInfo, true);
}
@Override
public void onFailure(final Throwable throwable) {
- LOG.warn("Starting/Stopping services for node {} was NOT successful, closing connection", nodeId);
- closeConnection(nodeId);
+ LOG.warn("{}ing services for node {} was NOT successful, closing connection", logText, deviceInfo);
+ closeConnection(deviceInfo);
}
});
}
}
@Override
- public DeviceContext getDeviceContext(final NodeId nodeId){
- return deviceManager.getDeviceContextFromNodeId(nodeId);
+ public DeviceContext getDeviceContext(DeviceInfo deviceInfo){
+ return deviceManager.gainContext(deviceInfo);
}
- public Short gainVersionSafely(final NodeId nodeId) {
- return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getFeatures().getVersion() : null;
+ @Override
+ public StatisticsContext getStatisticsContext(DeviceInfo deviceInfo){
+ return statisticsManager.gainContext(deviceInfo);
}
public Timeout newTimeout(@Nonnull TimerTask task, long delay, @Nonnull TimeUnit unit) {
return hashedWheelTimer.newTimeout(task, delay, unit);
}
- public ConnectionContext.CONNECTION_STATE gainConnectionStateSafely(final NodeId nodeId){
- return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getConnectionState() : null;
+ @Override
+ public ConnectionContext.CONNECTION_STATE gainConnectionStateSafely(final DeviceInfo deviceInfo){
+ return (null != getDeviceContext(deviceInfo)) ? getDeviceContext(deviceInfo).getPrimaryConnectionContext().getConnectionState() : null;
}
- public Long reserveXidForDeviceMessage(final NodeId nodeId){
- return null != getDeviceContext(nodeId) ? getDeviceContext(nodeId).reserveXidForDeviceMessage() : null;
+ @Override
+ public Long reserveXidForDeviceMessage(final DeviceInfo deviceInfo){
+ return null != getDeviceContext(deviceInfo) ? getDeviceContext(deviceInfo).reserveXidForDeviceMessage() : null;
}
@Override
- public void deviceStartInitializationDone(final NodeId nodeId, final boolean success) {
+ public void deviceStartInitializationDone(final DeviceInfo deviceInfo, final boolean success) {
if (!success) {
- LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
- closeConnection(nodeId);
+ LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", deviceInfo);
+ closeConnection(deviceInfo);
} else {
- LOG.info("initialization phase for node {} in device context was successful. Continuing to next context.", nodeId);
+ LOG.info("initialization phase for node {} in device context was successful. Continuing to next context.", deviceInfo);
}
}
@Override
- public void deviceInitializationDone(final NodeId nodeId, final boolean success) {
+ public void deviceInitializationDone(final DeviceInfo deviceInfo, final boolean success) {
if (!success) {
- LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
- closeConnection(nodeId);
+ LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", deviceInfo);
+ closeConnection(deviceInfo);
} else {
- LOG.info("initialization phase for node {} in device context was successful. All phases initialized OK.", nodeId);
+ LOG.info("initialization phase for node {} in device context was successful. All phases initialized OK.", deviceInfo);
}
}
@VisibleForTesting
- public boolean isServiceChangeListenersEmpty() {
+ boolean isServiceChangeListenersEmpty() {
return this.serviceChangeListeners.isEmpty();
}
+ @Override
+ public NotificationPublishService getNotificationPublishService() {
+ return notificationPublishService;
+ }
+
+ @Override
+ public void setNotificationPublishService(NotificationPublishService notificationPublishService) {
+ this.notificationPublishService = notificationPublishService;
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications 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.openflowplugin.impl;
+
+import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
+import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
+import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProviderFactory;
+import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of OpenFlowPluginProviderFactory.
+ *
+ * @author Thomas Pantelis
+ */
+public class OpenFlowPluginProviderFactoryImpl implements OpenFlowPluginProviderFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(OpenFlowPluginProviderFactoryImpl.class);
+
+ @Override
+ public OpenFlowPluginProvider newInstance(OpenflowProviderConfig providerConfig, DataBroker dataBroker,
+ RpcProviderRegistry rpcRegistry, NotificationService notificationService,
+ NotificationPublishService notificationPublishService,
+ EntityOwnershipService entityOwnershipService,
+ List<SwitchConnectionProvider> switchConnectionProviders) {
+
+ LOG.info("Initializing new OFP southbound.");
+
+ OpenflowPortsUtil.init();
+ OpenFlowPluginProvider openflowPluginProvider = new OpenFlowPluginProviderImpl(
+ providerConfig.getRpcRequestsQuota(),
+ providerConfig.getGlobalNotificationQuota(),
+ providerConfig.getThreadPoolMinThreads(),
+ providerConfig.getThreadPoolMaxThreads().getValue(),
+ providerConfig.getThreadPoolTimeout());
+
+ openflowPluginProvider.setSwitchConnectionProviders(switchConnectionProviders);
+ openflowPluginProvider.setDataBroker(dataBroker);
+ openflowPluginProvider.setRpcProviderRegistry(rpcRegistry);
+ openflowPluginProvider.setNotificationProviderService(notificationService);
+ openflowPluginProvider.setNotificationPublishService(notificationPublishService);
+ openflowPluginProvider.setEntityOwnershipService(entityOwnershipService);
+ openflowPluginProvider.setSwitchFeaturesMandatory(providerConfig.isSwitchFeaturesMandatory());
+ openflowPluginProvider.setIsStatisticsPollingOff(providerConfig.isIsStatisticsPollingOff());
+ openflowPluginProvider.setIsStatisticsRpcEnabled(providerConfig.isIsStatisticsRpcEnabled());
+ openflowPluginProvider.setBarrierCountLimit(providerConfig.getBarrierCountLimit().getValue());
+ openflowPluginProvider.setBarrierInterval(providerConfig.getBarrierIntervalTimeoutLimit().getValue());
+ openflowPluginProvider.setEchoReplyTimeout(providerConfig.getEchoReplyTimeout().getValue());
+
+ openflowPluginProvider.initialize();
+
+ LOG.info("Configured values, " +
+ "StatisticsPollingOff:{}, " +
+ "SwitchFeaturesMandatory:{}, " +
+ "BarrierCountLimit:{}, " +
+ "BarrierTimeoutLimit:{}, " +
+ "EchoReplyTimeout:{}, " +
+ "ThreadPoolMinThreads:{}, " +
+ "ThreadPoolMaxThreads:{}, " +
+ "ThreadPoolTimeout:{}",
+ providerConfig.isIsStatisticsPollingOff(),
+ providerConfig.isSwitchFeaturesMandatory(),
+ providerConfig.getBarrierCountLimit().getValue(),
+ providerConfig.getBarrierIntervalTimeoutLimit().getValue(),
+ providerConfig.getEchoReplyTimeout().getValue(),
+ providerConfig.getThreadPoolMinThreads(),
+ providerConfig.getThreadPoolMaxThreads().getValue(),
+ providerConfig.getThreadPoolTimeout());
+
+ return openflowPluginProvider;
+ }
+}
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.MessageIntelligenceAgencyImpl;
import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.MessageIntelligenceAgencyMXBean;
import org.opendaylight.openflowplugin.impl.util.TranslatorLibraryUtil;
+import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConverterManagerImpl;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
import org.slf4j.Logger;
private boolean isStatisticsRpcEnabled;
private final LifecycleConductor conductor;
+ private final ThreadPoolExecutor threadPool;
- public OpenFlowPluginProviderImpl(final long rpcRequestsQuota, final Long globalNotificationQuota) {
+ public OpenFlowPluginProviderImpl(final long rpcRequestsQuota,
+ final long globalNotificationQuota,
+ final int threadPoolMinThreads,
+ final int threadPoolMaxThreads,
+ final long threadPoolTimeout) {
Preconditions.checkArgument(rpcRequestsQuota > 0 && rpcRequestsQuota <= Integer.MAX_VALUE, "rpcRequestQuota has to be in range <1,%s>", Integer.MAX_VALUE);
this.rpcRequestsQuota = (int) rpcRequestsQuota;
this.globalNotificationQuota = Preconditions.checkNotNull(globalNotificationQuota);
+
+ // Creates a thread pool that creates new threads as needed, but will reuse previously
+ // constructed threads when they are available.
+ // Threads that have not been used for x seconds are terminated and removed from the cache.
+ threadPool = new ThreadPoolLoggingExecutor(
+ Preconditions.checkNotNull(threadPoolMinThreads),
+ Preconditions.checkNotNull(threadPoolMaxThreads),
+ Preconditions.checkNotNull(threadPoolTimeout), TimeUnit.SECONDS,
+ new SynchronousQueue<>(), "ofppool");
+
conductor = new LifecycleConductorImpl(messageIntelligenceAgency);
}
@Override
public void initialize() {
-
Preconditions.checkNotNull(dataBroker, "missing data broker");
Preconditions.checkNotNull(rpcProviderRegistry, "missing RPC provider registry");
Preconditions.checkNotNull(notificationProviderService, "missing notification provider service");
// TODO: rewrite later!
OFSessionUtil.getSessionManager().setExtensionConverterProvider(extensionConverterManager);
- connectionManager = new ConnectionManagerImpl(echoReplyTimeout);
+ connectionManager = new ConnectionManagerImpl(echoReplyTimeout, threadPool);
registerMXBean(messageIntelligenceAgency);
barrierInterval,
barrierCountLimit,
conductor);
+ ((ExtensionConverterProviderKeeper) conductor).setExtensionConverterProvider(extensionConverterManager);
((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager);
- conductor.setSafelyDeviceManager(deviceManager);
+ conductor.setSafelyManager(deviceManager);
+ conductor.setNotificationPublishService(notificationPublishService);
roleManager = new RoleManagerImpl(entityOwnershipService, dataBroker, conductor);
statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, isStatisticsPollingOff, conductor);
- conductor.setSafelyStatisticsManager(statisticsManager);
+ conductor.setSafelyManager(statisticsManager);
+
rpcManager = new RpcManagerImpl(rpcProviderRegistry, rpcRequestsQuota, conductor);
+ conductor.setSafelyManager(rpcManager);
roleManager.addRoleChangeListener((RoleChangeListener) conductor);
statisticsManager.setDeviceTerminationPhaseHandler(roleManager);
roleManager.setDeviceTerminationPhaseHandler(deviceManager);
- deviceManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
- deviceManager.setNotificationPublishService(notificationPublishService);
+ rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
TranslatorLibraryUtil.setBasicTranslatorLibrary(deviceManager);
deviceManager.initialize();
// TODO: needs to close org.opendaylight.openflowplugin.impl.role.OpenflowOwnershipListener after RoleContexts are down
// TODO: must not be executed prior to all living RoleContexts have been closed (via closing living DeviceContexts)
roleManager.close();
+
+ // Manually shutdown all remaining running threads in pool
+ threadPool.shutdown();
}
}
package org.opendaylight.openflowplugin.impl.connection;
+import com.google.common.base.Preconditions;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.SessionStatistics;
+import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private OutboundQueueProvider outboundQueueProvider;
private OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration;
private HandshakeContext handshakeContext;
+ private DeviceInfo deviceInfo;
/**
* @param connectionAdapter
connectionState = CONNECTION_STATE.WORKING;
}
+ @Override
+ public DeviceInfo getDeviceInfo() {
+ return this.deviceInfo;
+ }
+
+ @Override
+ public void handshakeSuccessful() {
+ Preconditions.checkNotNull(nodeId, "Cannot create DeviceInfo if 'NodeId' is not set!");
+ Preconditions.checkNotNull(featuresReply, "Cannot create DeviceInfo if 'features' is not set!");
+ this.deviceInfo = new DeviceInfoImpl(
+ nodeId,
+ DeviceStateUtil.createNodeInstanceIdentifier(nodeId),
+ featuresReply.getVersion(),
+ featuresReply.getDatapathId());
+ }
+
@Override
public void setHandshakeContext(HandshakeContext handshakeContext) {
this.handshakeContext = handshakeContext;
}
+
+
+ private class DeviceInfoImpl implements DeviceInfo {
+
+ final private NodeId nodeId;
+ final private KeyedInstanceIdentifier<Node, NodeKey> nodeII;
+ final private Short version;
+ final private BigInteger datapathId;
+
+ DeviceInfoImpl(
+ final NodeId nodeId,
+ final KeyedInstanceIdentifier<Node, NodeKey> nodeII,
+ final Short version,
+ final BigInteger datapathId) {
+ this.nodeId = nodeId;
+ this.nodeII = nodeII;
+ this.version = version;
+ this.datapathId = datapathId;
+ }
+
+ @Override
+ public NodeId getNodeId() {
+ return nodeId;
+ }
+
+ @Override
+ public KeyedInstanceIdentifier<Node, NodeKey> getNodeInstanceIdentifier() {
+ return nodeII;
+ }
+
+ @Override
+ public Short getVersion() {
+ return version;
+ }
+
+ @Override
+ public BigInteger getDatapathId() {
+ return datapathId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ DeviceInfoImpl that = (DeviceInfoImpl) o;
+
+ if (!nodeId.equals(that.nodeId)) return false;
+ if (!nodeII.equals(that.nodeII)) return false;
+ if (!version.equals(that.version)) return false;
+ return datapathId.equals(that.datapathId);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = nodeId.hashCode();
+ result = 31 * result + nodeII.hashCode();
+ result = 31 * result + version.hashCode();
+ result = 31 * result + datapathId.hashCode();
+ return result;
+ }
+ }
}
package org.opendaylight.openflowplugin.impl.connection;
import java.net.InetAddress;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ThreadPoolExecutor;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionReadyListener;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.impl.connection.listener.SystemNotificationsListenerImpl;
import org.opendaylight.openflowplugin.openflow.md.core.ErrorHandlerSimpleImpl;
import org.opendaylight.openflowplugin.openflow.md.core.HandshakeManagerImpl;
-import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
import org.slf4j.Logger;
private final boolean bitmapNegotiationEnabled = true;
private DeviceConnectedHandler deviceConnectedHandler;
private final long echoReplyTimeout;
+ private final ThreadPoolExecutor threadPool;
- public ConnectionManagerImpl(long echoReplyTimeout) {
+ public ConnectionManagerImpl(long echoReplyTimeout, final ThreadPoolExecutor threadPool) {
this.echoReplyTimeout = echoReplyTimeout;
+ this.threadPool = threadPool;
}
-
@Override
public void onSwitchConnected(final ConnectionAdapter connectionAdapter) {
-
- LOG.trace("preparing handshake: {}", connectionAdapter.getRemoteAddress());
-
- final int handshakeThreadLimit = 1;
- final ThreadPoolLoggingExecutor handshakePool = createHandshakePool(
- connectionAdapter.getRemoteAddress().toString(), handshakeThreadLimit);
-
LOG.trace("prepare connection context");
final ConnectionContext connectionContext = new ConnectionContextImpl(connectionAdapter);
final HandshakeManager handshakeManager = createHandshakeManager(connectionAdapter, handshakeListener);
LOG.trace("prepare handshake context");
- HandshakeContext handshakeContext = new HandshakeContextImpl(handshakePool, handshakeManager);
+ HandshakeContext handshakeContext = new HandshakeContextImpl(threadPool, handshakeManager);
handshakeListener.setHandshakeContext(handshakeContext);
connectionContext.setHandshakeContext(handshakeContext);
new OpenflowProtocolListenerInitialImpl(connectionContext, handshakeContext);
connectionAdapter.setMessageListener(ofMessageListener);
- final SystemNotificationsListener systemListener = new SystemNotificationsListenerImpl(connectionContext, echoReplyTimeout);
+ final SystemNotificationsListener systemListener = new SystemNotificationsListenerImpl(connectionContext, echoReplyTimeout, threadPool);
connectionAdapter.setSystemListener(systemListener);
LOG.trace("connection ballet finished");
}
- /**
- * @param connectionIdentifier
- * @param handshakeThreadLimit
- * @return
- */
- private static ThreadPoolLoggingExecutor createHandshakePool(
- final String connectionIdentifier, final int handshakeThreadLimit) {
- return new ThreadPoolLoggingExecutor(handshakeThreadLimit,
- handshakeThreadLimit, 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<>(HELLO_LIMIT), "OFHandshake-" + connectionIdentifier);
- }
-
/**
* @param connectionAdapter
* @param handshakeListener
return bitmapNegotiationEnabled;
}
-
@Override
public boolean accept(final InetAddress switchAddress) {
// TODO add connection accept logic based on address
package org.opendaylight.openflowplugin.impl.connection;
import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
import org.opendaylight.openflowplugin.api.openflow.md.core.HandshakeManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
*
*/
public class HandshakeContextImpl implements HandshakeContext {
-
- private static final Logger LOG = LoggerFactory.getLogger(HandshakeContextImpl.class);
-
private ThreadPoolExecutor handshakePool;
private HandshakeManager handshakeManager;
}
@Override
- public void close() throws Exception {
- shutdownPoolPolitely();
- }
-
- private void shutdownPoolPolitely() {
- LOG.debug("terminating handshake pool");
- handshakePool.shutdown();
- try {
- handshakePool.awaitTermination(1, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- LOG.error("Error while awaiting termination on pool. Will use shutdownNow method.");
- } finally {
- handshakePool.purge();
- if (! handshakePool.isTerminated()) {
- handshakePool.shutdownNow();
- }
- LOG.debug("pool is terminated: {}", handshakePool.isTerminated());
- }
+ public void close() {
}
}
connectionContext.changeStateToWorking();
connectionContext.setFeatures(featureOutput);
connectionContext.setNodeId(InventoryDataServiceUtil.nodeIdFromDatapathId(featureOutput.getDatapathId()));
+ connectionContext.handshakeSuccessful();
// fire barrier in order to sweep all handshake and posthandshake messages before continue
final ListenableFuture<RpcResult<BarrierOutput>> barrier = fireBarrier(version, 0L);
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
@VisibleForTesting
static final long MAX_ECHO_REPLY_TIMEOUT = 2000;
private final long echoReplyTimeout;
+ private final ThreadPoolExecutor threadPool;
- public SystemNotificationsListenerImpl(@Nonnull final ConnectionContext connectionContext, long echoReplyTimeout) {
+ public SystemNotificationsListenerImpl(@Nonnull final ConnectionContext connectionContext,
+ long echoReplyTimeout,
+ @Nonnull final ThreadPoolExecutor threadPool) {
+ this.threadPool = threadPool;
this.connectionContext = Preconditions.checkNotNull(connectionContext);
this.echoReplyTimeout = echoReplyTimeout;
}
@Override
public void onSwitchIdleEvent(final SwitchIdleEvent notification) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- boolean shouldBeDisconnected = true;
+ threadPool.execute(() -> {
+ boolean shouldBeDisconnected = true;
- final InetSocketAddress remoteAddress = connectionContext.getConnectionAdapter().getRemoteAddress();
+ final InetSocketAddress remoteAddress = connectionContext.getConnectionAdapter().getRemoteAddress();
- if (ConnectionContext.CONNECTION_STATE.WORKING.equals(connectionContext.getConnectionState())) {
- FeaturesReply features = connectionContext.getFeatures();
- LOG.info("Switch Idle state occurred, node={}|auxId={}", remoteAddress, features.getAuxiliaryId());
- connectionContext.changeStateToTimeouting();
- EchoInputBuilder builder = new EchoInputBuilder();
- builder.setVersion(features.getVersion());
- Xid xid = new Xid(0L);
- builder.setXid(xid.getValue());
+ if (ConnectionContext.CONNECTION_STATE.WORKING.equals(connectionContext.getConnectionState())) {
+ FeaturesReply features = connectionContext.getFeatures();
+ LOG.info("Switch Idle state occurred, node={}|auxId={}", remoteAddress, features.getAuxiliaryId());
+ connectionContext.changeStateToTimeouting();
+ EchoInputBuilder builder = new EchoInputBuilder();
+ builder.setVersion(features.getVersion());
+ Xid xid = new Xid(0L);
+ builder.setXid(xid.getValue());
- Future<RpcResult<EchoOutput>> echoReplyFuture = connectionContext.getConnectionAdapter().echo(builder.build());
+ Future<RpcResult<EchoOutput>> echoReplyFuture = connectionContext.getConnectionAdapter().echo(builder.build());
- try {
- RpcResult<EchoOutput> echoReplyValue = echoReplyFuture.get(echoReplyTimeout, TimeUnit.MILLISECONDS);
- if (echoReplyValue.isSuccessful()) {
- connectionContext.changeStateToWorking();
- shouldBeDisconnected = false;
- } else {
- for (RpcError replyError : echoReplyValue.getErrors()) {
- Throwable cause = replyError.getCause();
- if (LOG.isWarnEnabled()) {
- LOG.warn("Received EchoReply from [{}] in TIMEOUTING state, Error:{}", remoteAddress, cause.getMessage());
- }
-
- if (LOG.isTraceEnabled()) {
- LOG.trace("Received EchoReply from [{}] in TIMEOUTING state, Error:{}", remoteAddress, cause);
- }
+ try {
+ RpcResult<EchoOutput> echoReplyValue = echoReplyFuture.get(echoReplyTimeout, TimeUnit.MILLISECONDS);
+ if (echoReplyValue.isSuccessful()) {
+ connectionContext.changeStateToWorking();
+ shouldBeDisconnected = false;
+ } else {
+ for (RpcError replyError : echoReplyValue.getErrors()) {
+ Throwable cause = replyError.getCause();
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Received EchoReply from [{}] in TIMEOUTING state, Error:{}", remoteAddress, cause.getMessage());
+ }
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Received EchoReply from [{}] in TIMEOUTING state, Error:{}", remoteAddress, cause);
}
- }
- } catch (Exception e) {
- if (LOG.isWarnEnabled()) {
- LOG.warn("Exception while waiting for echoReply from [{}] in TIMEOUTING state: {}", remoteAddress, e.getMessage());
- }
- if (LOG.isTraceEnabled()) {
- LOG.trace("Exception while waiting for echoReply from [{}] in TIMEOUTING state: {}", remoteAddress, e);
}
-
}
- }
- if (shouldBeDisconnected) {
- if (LOG.isInfoEnabled()) {
- LOG.info("ConnectionEvent:Closing connection as device is idle. Echo sent at {}. Device:{}, NodeId:{}",
- new Date(System.currentTimeMillis() - echoReplyTimeout), remoteAddress, connectionContext.getNodeId());
+ } catch (Exception e) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Exception while waiting for echoReply from [{}] in TIMEOUTING state: {}", remoteAddress, e.getMessage());
+ }
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Exception while waiting for echoReply from [{}] in TIMEOUTING state: {}", remoteAddress, e);
}
- connectionContext.closeConnection(true);
}
}
- }).start();
+ if (shouldBeDisconnected) {
+ if (LOG.isInfoEnabled()) {
+ LOG.info("ConnectionEvent:Closing connection as device is idle. Echo sent at {}. Device:{}, NodeId:{}",
+ new Date(System.currentTimeMillis() - echoReplyTimeout), remoteAddress, connectionContext.getNodeId());
+ }
+
+ connectionContext.closeConnection(true);
+ }
+ });
}
}
package org.opendaylight.openflowplugin.impl.device;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
-import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleKeeper;
-import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
-import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderKeeper;
import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
import org.opendaylight.openflowplugin.impl.registry.group.DeviceGroupRegistryImpl;
import org.opendaylight.openflowplugin.impl.registry.meter.DeviceMeterRegistryImpl;
-import org.opendaylight.openflowplugin.impl.rpc.RpcContextImpl;
-import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtils;
-import org.opendaylight.openflowplugin.impl.util.MdSalRegistrationUtils;
import org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.ExperimenterMessageFromDevBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-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.node.NodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
private final MessageTranslator<PacketInMessage, PacketReceived> packetInTranslator;
private final MessageTranslator<FlowRemoved, org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved> flowRemovedTranslator;
private final TranslatorLibrary translatorLibrary;
- private final Map<Long, NodeConnectorRef> nodeConnectorCache;
private final ItemLifeCycleRegistry itemLifeCycleSourceRegistry;
- private RpcContext rpcContext;
private ExtensionConverterProvider extensionConverterProvider;
- private final boolean switchFeaturesMandatory;
- private StatisticsContext statisticsContext;
-
- private final NodeId nodeId;
-
- private volatile DEVICE_CONTEXT_STATE deviceCtxState;
- private boolean isStatisticsRpcEnabled;
+ private final DeviceInfo deviceInfo;
+ private volatile CONTEXT_STATE contextState;
@VisibleForTesting
DeviceContextImpl(@Nonnull final ConnectionContext primaryConnectionContext,
@Nonnull final DataBroker dataBroker,
@Nonnull final LifecycleConductor conductor,
@Nonnull final OutboundQueueProvider outboundQueueProvider,
- @Nonnull final TranslatorLibrary translatorLibrary,
- final boolean switchFeaturesMandatory) {
- this.switchFeaturesMandatory = switchFeaturesMandatory;
+ @Nonnull final TranslatorLibrary translatorLibrary) {
this.primaryConnectionContext = Preconditions.checkNotNull(primaryConnectionContext);
this.deviceState = Preconditions.checkNotNull(deviceState);
this.dataBroker = Preconditions.checkNotNull(dataBroker);
Preconditions.checkNotNull(conductor);
this.outboundQueueProvider = Preconditions.checkNotNull(outboundQueueProvider);
- this.transactionChainManager = new TransactionChainManager(dataBroker, deviceState, conductor);
+ deviceInfo = primaryConnectionContext.getDeviceInfo();
+ this.transactionChainManager = new TransactionChainManager(dataBroker, deviceInfo, conductor);
auxiliaryConnectionContexts = new HashMap<>();
deviceFlowRegistry = new DeviceFlowRegistryImpl();
deviceGroupRegistry = new DeviceGroupRegistryImpl();
deviceMeterRegistry = new DeviceMeterRegistryImpl();
messageSpy = conductor.getMessageIntelligenceAgency();
+
packetInLimiter = new PacketInRateLimiter(primaryConnectionContext.getConnectionAdapter(),
/*initial*/ 1000, /*initial*/2000, messageSpy, REJECTED_DRAIN_FACTOR);
this.translatorLibrary = translatorLibrary;
portStatusTranslator = translatorLibrary.lookupTranslator(
- new TranslatorKey(deviceState.getVersion(), PortGrouping.class.getName()));
+ new TranslatorKey(deviceInfo.getVersion(), PortGrouping.class.getName()));
packetInTranslator = translatorLibrary.lookupTranslator(
- new TranslatorKey(deviceState.getVersion(), PacketIn.class.getName()));
+ new TranslatorKey(deviceInfo.getVersion(), PacketIn.class.getName()));
flowRemovedTranslator = translatorLibrary.lookupTranslator(
- new TranslatorKey(deviceState.getVersion(), FlowRemoved.class.getName()));
-
-
- nodeConnectorCache = new ConcurrentHashMap<>();
+ new TranslatorKey(deviceInfo.getVersion(), FlowRemoved.class.getName()));
itemLifeCycleSourceRegistry = new ItemLifeCycleRegistryImpl();
flowLifeCycleKeeper = new ItemLifeCycleSourceImpl();
itemLifeCycleSourceRegistry.registerLifeCycleSource(flowLifeCycleKeeper);
- deviceCtxState = DEVICE_CONTEXT_STATE.INITIALIZATION;
-
- nodeId = primaryConnectionContext.getNodeId();
+ contextState = CONTEXT_STATE.INITIALIZATION;
}
/**
public void removeAuxiliaryConnectionContext(final ConnectionContext connectionContext) {
final SwitchConnectionDistinguisher connectionDistinguisher = createConnectionDistinguisher(connectionContext);
LOG.debug("auxiliary connection dropped: {}, nodeId:{}", connectionContext.getConnectionAdapter()
- .getRemoteAddress(), nodeId);
+ .getRemoteAddress(), deviceInfo.getNodeId());
auxiliaryConnectionContexts.remove(connectionDistinguisher);
}
}
@Override
- public ReadOnlyTransaction getReadTransaction() {
- return dataBroker.newReadOnlyTransaction();
- }
-
- @Override
- public ListenableFuture<Void> onClusterRoleChange(final OfpRole oldRole, @CheckForNull final OfpRole role) {
- LOG.trace("onClusterRoleChange {} for node:", role, nodeId);
- Preconditions.checkArgument(role != null);
- if (role.equals(oldRole)) {
- LOG.debug("Demanded role change for device {} is not changed. OldRole: {}, NewRole {}", nodeId, oldRole, role);
- return Futures.immediateFuture(null);
- }
- if (OfpRole.BECOMEMASTER.equals(role)) {
- return onDeviceTakeClusterLeadership();
- } else if (OfpRole.BECOMESLAVE.equals(role)) {
- return onDeviceLostClusterLeadership();
- } else {
- LOG.warn("Unknown OFCluster Role {} for Node {}", role, nodeId);
- if (null != rpcContext) {
- MdSalRegistrationUtils.unregisterServices(rpcContext);
- }
- return transactionChainManager.deactivateTransactionManager();
- }
+ public DeviceInfo getDeviceInfo() {
+ return this.deviceInfo;
}
@Override
- public ListenableFuture<Void> onDeviceLostClusterLeadership() {
- LOG.trace("onDeviceLostClusterLeadership for node: {}", nodeId);
- if (null != rpcContext) {
- MdSalRegistrationUtils.registerSlaveServices(rpcContext, OfpRole.BECOMESLAVE);
- }
- return transactionChainManager.deactivateTransactionManager();
- }
-
- @Override
- public ListenableFuture<Void> onDeviceTakeClusterLeadership() {
- LOG.trace("onDeviceTakeClusterLeadership for node: {}", nodeId);
- /* validation */
- if (statisticsContext == null) {
- final String errMsg = String.format("DeviceCtx %s is up but we are missing StatisticsContext", nodeId);
- LOG.warn(errMsg);
- return Futures.immediateFailedFuture(new IllegalStateException(errMsg));
- }
- if (rpcContext == null) {
- final String errMsg = String.format("DeviceCtx %s is up but we are missing RpcContext", nodeId);
- LOG.warn(errMsg);
- return Futures.immediateFailedFuture(new IllegalStateException(errMsg));
- }
- /* Routed RPC registration */
- MdSalRegistrationUtils.registerMasterServices(getRpcContext(), DeviceContextImpl.this, OfpRole.BECOMEMASTER);
-
- if (isStatisticsRpcEnabled) {
- MdSalRegistrationUtils.registerStatCompatibilityServices(getRpcContext(), this,
- notificationPublishService, new AtomicLong());
- }
-
- /* Prepare init info collecting */
- getDeviceState().setDeviceSynchronized(false);
- transactionChainManager.activateTransactionManager();
- /* Init Collecting NodeInfo */
- final ListenableFuture<Void> initCollectingDeviceInfo = DeviceInitializationUtils.initializeNodeInformation(
- DeviceContextImpl.this, switchFeaturesMandatory);
- /* Init Collecting StatInfo */
- final ListenableFuture<Boolean> statPollFuture = Futures.transform(initCollectingDeviceInfo,
- new AsyncFunction<Void, Boolean>() {
-
- @Override
- public ListenableFuture<Boolean> apply(@Nonnull final Void input) throws Exception {
- getStatisticsContext().statListForCollectingInitialization();
- return getStatisticsContext().gatherDynamicData();
- }
- });
-
- return Futures.transform(statPollFuture, new Function<Boolean, Void>() {
-
- @Override
- public Void apply(final Boolean input) {
- if (ConnectionContext.CONNECTION_STATE.RIP.equals(getPrimaryConnectionContext().getConnectionState())) {
- final String errMsg = String.format("We lost connection for Device %s, context has to be closed.",
- getDeviceState().getNodeId());
- LOG.warn(errMsg);
- throw new IllegalStateException(errMsg);
- }
- if (!input) {
- final String errMsg = String.format("Get Initial Device %s information fails",
- getDeviceState().getNodeId());
- LOG.warn(errMsg);
- throw new IllegalStateException(errMsg);
- }
- LOG.debug("Get Initial Device {} information is successful", nodeId);
- getDeviceState().setDeviceSynchronized(true);
- initialSubmitTransaction();
- getDeviceState().setStatisticsPollingEnabledProp(true);
- return null;
- }
- });
+ public ReadOnlyTransaction getReadTransaction() {
+ return dataBroker.newReadOnlyTransaction();
}
@Override
@Override
public void processFlowRemovedMessage(final FlowRemoved flowRemoved) {
+ //1. translate to general flow (table, priority, match, cookie)
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved flowRemovedNotification =
+ flowRemovedTranslator.translate(flowRemoved, deviceInfo, null);
+ // Trigger off a notification
+ notificationPublishService.offerNotification(flowRemovedNotification);
+
final ItemLifecycleListener itemLifecycleListener = flowLifeCycleKeeper.getItemLifecycleListener();
if (itemLifecycleListener != null) {
- //1. translate to general flow (table, priority, match, cookie)
- final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved flowRemovedNotification =
- flowRemovedTranslator.translate(flowRemoved, this.getDeviceState(), null);
//2. create registry key
final FlowRegistryKey flowRegKey = FlowRegistryKeyFactory.create(flowRemovedNotification);
//3. lookup flowId
//4. if flowId present:
if (flowDescriptor != null) {
// a) construct flow path
- final KeyedInstanceIdentifier<Flow, FlowKey> flowPath = getDeviceState().getNodeInstanceIdentifier()
+ final KeyedInstanceIdentifier<Flow, FlowKey> flowPath = getDeviceInfo().getNodeInstanceIdentifier()
.augmentation(FlowCapableNode.class)
.child(Table.class, flowDescriptor.getTableKey())
.child(Flow.class, new FlowKey(flowDescriptor.getFlowId()));
itemLifecycleListener.onRemoved(flowPath);
} else {
LOG.debug("flow id not found: nodeId={} tableId={}, priority={}",
- getDeviceState().getNodeId(), flowRegKey.getTableId(), flowRemovedNotification.getPriority());
+ getDeviceInfo().getNodeId(), flowRegKey.getTableId(), flowRemovedNotification.getPriority());
}
}
}
@Override
public void processPortStatusMessage(final PortStatusMessage portStatus) {
messageSpy.spyMessage(portStatus.getImplementedInterface(), MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS);
- final FlowCapableNodeConnector flowCapableNodeConnector = portStatusTranslator.translate(portStatus, this.getDeviceState(), null);
+ final FlowCapableNodeConnector flowCapableNodeConnector = portStatusTranslator.translate(portStatus, deviceInfo, null);
final KeyedInstanceIdentifier<NodeConnector, NodeConnectorKey> iiToNodeConnector = provideIIToNodeConnector(portStatus.getPortNo(), portStatus.getVersion());
try {
}
private KeyedInstanceIdentifier<NodeConnector, NodeConnectorKey> provideIIToNodeConnector(final long portNo, final short version) {
- final InstanceIdentifier<Node> iiToNodes = deviceState.getNodeInstanceIdentifier();
- final BigInteger dataPathId = deviceState.getFeatures().getDatapathId();
+ final InstanceIdentifier<Node> iiToNodes = deviceInfo.getNodeInstanceIdentifier();
+ final BigInteger dataPathId = deviceInfo.getDatapathId();
final NodeConnectorId nodeConnectorId = NodeStaticReplyTranslatorUtil.nodeConnectorId(dataPathId.toString(), portNo, version);
return iiToNodes.child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId));
}
public void processPacketInMessage(final PacketInMessage packetInMessage) {
messageSpy.spyMessage(packetInMessage.getImplementedInterface(), MessageSpy.STATISTIC_GROUP.FROM_SWITCH);
final ConnectionAdapter connectionAdapter = getPrimaryConnectionContext().getConnectionAdapter();
- final PacketReceived packetReceived = packetInTranslator.translate(packetInMessage, this.getDeviceState(), null);
+ final PacketReceived packetReceived = packetInTranslator.translate(packetInMessage, deviceInfo, null);
if (packetReceived == null) {
LOG.debug("Received a null packet from switch {}", connectionAdapter.getRemoteAddress());
// lookup converter
final ExperimenterDataOfChoice vendorData = notification.getExperimenterDataOfChoice();
final MessageTypeKey<? extends ExperimenterDataOfChoice> key = new MessageTypeKey<>(
- deviceState.getVersion(),
+ deviceInfo.getVersion(),
(Class<? extends ExperimenterDataOfChoice>) vendorData.getImplementedInterface());
final ConvertorMessageFromOFJava<ExperimenterDataOfChoice, MessagePath> messageConverter = extensionConverterProvider.getMessageConverter(key);
if (messageConverter == null) {
LOG.warn("custom converter for {}[OF:{}] not found",
notification.getExperimenterDataOfChoice().getImplementedInterface(),
- deviceState.getVersion());
+ deviceInfo.getVersion());
return;
}
// build notification
try {
messageOfChoice = messageConverter.convert(vendorData, MessagePath.MESSAGE_NOTIFICATION);
final ExperimenterMessageFromDevBuilder experimenterMessageFromDevBld = new ExperimenterMessageFromDevBuilder()
- .setNode(new NodeRef(deviceState.getNodeInstanceIdentifier()))
+ .setNode(new NodeRef(deviceInfo.getNodeInstanceIdentifier()))
.setExperimenterMessageOfChoice(messageOfChoice);
// publish
notificationPublishService.offerNotification(experimenterMessageFromDevBld.build());
public synchronized void close() {
LOG.debug("closing deviceContext: {}, nodeId:{}",
getPrimaryConnectionContext().getConnectionAdapter().getRemoteAddress(),
- getDeviceState().getNodeId());
+ getDeviceInfo().getNodeId());
// NOOP
throw new UnsupportedOperationException("Autocloseble.close will be removed soon");
}
@Override
public void onPublished() {
- Verify.verify(DEVICE_CONTEXT_STATE.INITIALIZATION.equals(deviceCtxState));
- deviceCtxState = DEVICE_CONTEXT_STATE.WORKING;
+ Verify.verify(CONTEXT_STATE.INITIALIZATION.equals(contextState));
+ contextState = CONTEXT_STATE.WORKING;
primaryConnectionContext.getConnectionAdapter().setPacketInFiltering(false);
for (final ConnectionContext switchAuxConnectionContext : auxiliaryConnectionContexts.values()) {
switchAuxConnectionContext.getConnectionAdapter().setPacketInFiltering(false);
return new MultiMsgCollectorImpl(this, requestContext);
}
- @Override
- public NodeConnectorRef lookupNodeConnectorRef(final Long portNumber) {
- return nodeConnectorCache.get(portNumber);
- }
-
- @Override
- public void storeNodeConnectorRef(@Nonnull final Long portNumber, @Nonnull final NodeConnectorRef nodeConnectorRef) {
- nodeConnectorCache.put(
- Preconditions.checkNotNull(portNumber),
- Preconditions.checkNotNull(nodeConnectorRef));
- }
-
@Override
public void updatePacketInRateLimit(final long upperBound) {
packetInLimiter.changeWaterMarks((int) (LOW_WATERMARK_FACTOR * upperBound), (int) (HIGH_WATERMARK_FACTOR * upperBound));
return itemLifeCycleSourceRegistry;
}
- @Override
- public void setRpcContext(final RpcContext rpcContext) {
- this.rpcContext = rpcContext;
- }
-
- @Override
- public RpcContext getRpcContext() {
- return rpcContext;
- }
-
@Override
public void setExtensionConverterProvider(final ExtensionConverterProvider extensionConverterProvider) {
this.extensionConverterProvider = extensionConverterProvider;
return extensionConverterProvider;
}
- @Override
- public void setStatisticsContext(final StatisticsContext statisticsContext) {
- this.statisticsContext = statisticsContext;
- }
-
- @Override
- public StatisticsContext getStatisticsContext() {
- return statisticsContext;
- }
-
@Override
public synchronized void shutdownConnection() {
- LOG.debug("Shutdown method for node {}", nodeId);
- deviceState.setValid(false);
- if (DEVICE_CONTEXT_STATE.TERMINATION.equals(deviceCtxState)) {
- LOG.debug("DeviceCtx for Node {} is in termination process.", nodeId);
+ LOG.debug("Shutdown method for node {}", deviceInfo.getNodeId());
+ if (CONTEXT_STATE.TERMINATION.equals(contextState)) {
+ LOG.debug("DeviceCtx for Node {} is in termination process.", deviceInfo.getNodeId());
return;
}
- deviceCtxState = DEVICE_CONTEXT_STATE.TERMINATION;
+ contextState = CONTEXT_STATE.TERMINATION;
if (ConnectionContext.CONNECTION_STATE.RIP.equals(getPrimaryConnectionContext().getConnectionState())) {
- LOG.debug("ConnectionCtx for Node {} is in RIP state.", deviceState.getNodeId());
+ LOG.debug("ConnectionCtx for Node {} is in RIP state.", deviceInfo.getNodeId());
return;
}
/* Terminate Auxiliary Connection */
deviceMeterRegistry.close();
}
- @Override
- public void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled) {
- this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
- }
-
- @Override
- public DEVICE_CONTEXT_STATE getDeviceContextState() {
- return deviceCtxState;
- }
-
@Override
public ListenableFuture<Void> shuttingDownDataStoreTransactions() {
- deviceState.setValid(false);
return transactionChainManager.shuttingDown();
}
TransactionChainManager getTransactionChainManager() {
return this.transactionChainManager;
}
+
+ @Override
+ public CONTEXT_STATE getState() {
+ return this.contextState;
+ }
}
package org.opendaylight.openflowplugin.impl.device;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.Iterators;
+import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceSynchronizeListener;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceValidListener;
import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderKeeper;
import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
import org.opendaylight.openflowplugin.impl.connection.OutboundQueueProviderImpl;
import org.opendaylight.openflowplugin.impl.device.listener.OpenflowProtocolListenerFullImpl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private TranslatorLibrary translatorLibrary;
private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
- private NotificationPublishService notificationPublishService;
- private final ConcurrentMap<NodeId, DeviceContext> deviceContexts = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceInfo, DeviceContext> deviceContexts = new ConcurrentHashMap<>();
private final long barrierIntervalNanos;
private final int barrierCountLimit;
private ExtensionConverterProvider extensionConverterProvider;
private ScheduledThreadPoolExecutor spyPool;
+ private Set<DeviceSynchronizeListener> deviceSynchronizedListeners;
+ private Set<DeviceValidListener> deviceValidListeners;
private final LifecycleConductor conductor;
- private boolean isStatisticsRpcEnabled;
public DeviceManagerImpl(@Nonnull final DataBroker dataBroker,
final long globalNotificationQuota, final boolean switchFeaturesMandatory,
this.conductor = lifecycleConductor;
spyPool = new ScheduledThreadPoolExecutor(1);
+ this.deviceSynchronizedListeners = new HashSet<>();
+ this.deviceValidListeners = new HashSet<>();
}
}
@Override
- public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
+ public void onDeviceContextLevelUp(@CheckForNull DeviceInfo deviceInfo) throws Exception {
// final phase - we have to add new Device to MD-SAL DataStore
- LOG.debug("Final phase of DeviceContextLevelUp for Node: {} ", nodeId);
- DeviceContext deviceContext = Preconditions.checkNotNull(deviceContexts.get(nodeId));
+ LOG.debug("Final phase of DeviceContextLevelUp for Node: {} ", deviceInfo.getNodeId());
+ DeviceContext deviceContext = Preconditions.checkNotNull(deviceContexts.get(deviceInfo));
((DeviceContextImpl) deviceContext).initialSubmitTransaction();
deviceContext.onPublished();
}
public boolean deviceConnected(@CheckForNull final ConnectionContext connectionContext) throws Exception {
Preconditions.checkArgument(connectionContext != null);
- NodeId nodeId = connectionContext.getNodeId();
+ DeviceInfo deviceInfo = connectionContext.getDeviceInfo();
/**
* This part prevent destroy another device context. Throwing here an exception result to propagate close connection
* in {@link org.opendaylight.openflowplugin.impl.connection.org.opendaylight.openflowplugin.impl.connection.HandshakeContextImpl}
* If context already exist we are in state closing process (connection flapping) and we should not propagate connection close
*/
- if (deviceContexts.containsKey(nodeId)) {
+ if (deviceContexts.containsKey(deviceInfo)) {
LOG.warn("Rejecting connection from node which is already connected and there exist deviceContext for it: {}", connectionContext.getNodeId());
return false;
}
LOG.info("ConnectionEvent: Device connected to controller, Device:{}, NodeId:{}",
- connectionContext.getConnectionAdapter().getRemoteAddress(), nodeId);
+ connectionContext.getConnectionAdapter().getRemoteAddress(), deviceInfo.getNodeId());
// Add Disconnect handler
connectionContext.setDeviceDisconnectedHandler(DeviceManagerImpl.this);
//FIXME: as soon as auxiliary connection are fully supported then this is needed only before device context published
connectionAdapter.setPacketInFiltering(true);
- final Short version = connectionContext.getFeatures().getVersion();
- final OutboundQueueProvider outboundQueueProvider = new OutboundQueueProviderImpl(version);
+ final OutboundQueueProvider outboundQueueProvider = new OutboundQueueProviderImpl(deviceInfo.getVersion());
connectionContext.setOutboundQueueProvider(outboundQueueProvider);
final OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration =
connectionAdapter.registerOutboundQueueHandler(outboundQueueProvider, barrierCountLimit, barrierIntervalNanos);
connectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration);
- final DeviceState deviceState = createDeviceState(connectionContext);
+ final DeviceState deviceState = new DeviceStateImpl(deviceInfo);
+ this.addDeviceSynchronizeListener(deviceState);
+ this.addDeviceValidListener(deviceState);
+
final DeviceContext deviceContext = new DeviceContextImpl(connectionContext,
deviceState,
dataBroker,
conductor,
outboundQueueProvider,
- translatorLibrary,
- switchFeaturesMandatory);
+ translatorLibrary);
- Verify.verify(deviceContexts.putIfAbsent(nodeId, deviceContext) == null, "DeviceCtx still not closed.");
+ Verify.verify(deviceContexts.putIfAbsent(deviceInfo, deviceContext) == null, "DeviceCtx still not closed.");
((ExtensionConverterProviderKeeper) deviceContext).setExtensionConverterProvider(extensionConverterProvider);
- deviceContext.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
- deviceContext.setNotificationPublishService(notificationPublishService);
+ deviceContext.setNotificationPublishService(conductor.getNotificationPublishService());
updatePacketInRateLimiters();
final OpenflowProtocolListenerFullImpl messageListener = new OpenflowProtocolListenerFullImpl(
connectionAdapter, deviceContext);
connectionAdapter.setMessageListener(messageListener);
- deviceState.setValid(true);
+ notifyDeviceValidListeners(deviceInfo, true);
- deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
+ deviceInitPhaseHandler.onDeviceContextLevelUp(connectionContext.getDeviceInfo());
- return true;
- }
+ notifyDeviceSynchronizeListeners(deviceInfo, true);
- private static DeviceStateImpl createDeviceState(final @Nonnull ConnectionContext connectionContext) {
- return new DeviceStateImpl(connectionContext.getFeatures(), connectionContext.getNodeId());
+ return true;
}
private void updatePacketInRateLimiters() {
this.translatorLibrary = translatorLibrary;
}
- @Override
- public void setNotificationPublishService(final NotificationPublishService notificationService) {
- notificationPublishService = notificationService;
- }
-
@Override
public void close() {
for (final Iterator<DeviceContext> iterator = Iterators.consumingIterator(deviceContexts.values().iterator());
iterator.hasNext();) {
final DeviceContext deviceCtx = iterator.next();
+ notifyDeviceValidListeners(deviceCtx.getDeviceInfo(), false);
deviceCtx.shutdownConnection();
deviceCtx.shuttingDownDataStoreTransactions();
}
}
@Override
- public void onDeviceContextLevelDown(final DeviceContext deviceContext) {
- LOG.debug("onDeviceContextClosed for Node {}", deviceContext.getDeviceState().getNodeId());
- deviceContexts.remove(deviceContext.getPrimaryConnectionContext().getNodeId(), deviceContext);
+ public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
+ LOG.debug("onDeviceContextClosed for Node {}", deviceInfo.getNodeId());
+ deviceContexts.remove(deviceInfo);
updatePacketInRateLimiters();
}
spyPool.scheduleAtFixedRate(conductor.getMessageIntelligenceAgency(), spyRate, spyRate, TimeUnit.SECONDS);
}
- @Override
- public DeviceContext getDeviceContextFromNodeId(final NodeId nodeId) {
- return deviceContexts.get(nodeId);
- }
-
- @Override
- public void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled) {
- this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
- }
-
@Override
public void setExtensionConverterProvider(final ExtensionConverterProvider extensionConverterProvider) {
this.extensionConverterProvider = extensionConverterProvider;
@Override
public void onDeviceDisconnected(final ConnectionContext connectionContext) {
LOG.trace("onDeviceDisconnected method call for Node: {}", connectionContext.getNodeId());
- final NodeId nodeId = connectionContext.getNodeId();
- final DeviceContext deviceCtx = this.deviceContexts.get(nodeId);
+ final DeviceInfo deviceInfo = connectionContext.getDeviceInfo();
+ final DeviceContext deviceCtx = this.deviceContexts.get(deviceInfo);
if (null == deviceCtx) {
- LOG.info("DeviceContext for Node {} was not found. Connection is terminated without OFP context suite.", nodeId);
+ LOG.info("DeviceContext for Node {} was not found. Connection is terminated without OFP context suite.", deviceInfo.getNodeId());
return;
}
/* Connection is not PrimaryConnection so try to remove from Auxiliary Connections */
deviceCtx.removeAuxiliaryConnectionContext(connectionContext);
} else {
+ notifyDeviceValidListeners(deviceInfo, false);
/* Device is disconnected and so we need to close TxManager */
final ListenableFuture<Void> future = deviceCtx.shuttingDownDataStoreTransactions();
Futures.addCallback(future, new FutureCallback<Void>() {
@Override
public void onSuccess(final Void result) {
- LOG.debug("TxChainManager for device {} is closed successful.", nodeId);
- deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceCtx);
+ LOG.debug("TxChainManager for device {} is closed successful.", deviceInfo.getNodeId());
+ deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
}
@Override
public void onFailure(final Throwable t) {
- LOG.warn("TxChainManager for device {} failed by closing.", nodeId, t);
- deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceCtx);
+ LOG.warn("TxChainManager for device {} failed by closing.", deviceInfo.getNodeId(), t);
+ deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
}
});
/* Add timer for Close TxManager because it could fain ind cluster without notification */
- final TimerTask timerTask = new TimerTask() {
-
- @Override
- public void run(final Timeout timeout) throws Exception {
- if (!future.isDone()) {
- LOG.info("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.", nodeId);
- future.cancel(false);
- }
+ final TimerTask timerTask = timeout -> {
+ if (!future.isDone()) {
+ LOG.info("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.", deviceInfo.getNodeId());
+ future.cancel(false);
}
};
conductor.newTimeout(timerTask, 10, TimeUnit.SECONDS);
}
@VisibleForTesting
- void addDeviceContextToMap(final NodeId nodeId, final DeviceContext deviceContext){
- deviceContexts.put(nodeId, deviceContext);
+ void addDeviceContextToMap(final DeviceInfo deviceInfo, final DeviceContext deviceContext){
+ deviceContexts.put(deviceInfo, deviceContext);
+ }
+
+ @Override
+ public <T extends OFPContext> T gainContext(final DeviceInfo deviceInfo) {
+ return (T) deviceContexts.get(deviceInfo);
+ }
+
+ @Override
+ public ListenableFuture<Void> onClusterRoleChange(final DeviceInfo deviceInfo, final OfpRole role) {
+ DeviceContext deviceContext = conductor.getDeviceContext(deviceInfo);
+ LOG.trace("onClusterRoleChange {} for node:", role, deviceInfo.getNodeId());
+ if (OfpRole.BECOMEMASTER.equals(role)) {
+ return onDeviceTakeClusterLeadership(deviceInfo);
+ }
+ return ((DeviceContextImpl)deviceContext).getTransactionChainManager().deactivateTransactionManager();
}
+
+ @Override
+ public void addDeviceSynchronizeListener(final DeviceSynchronizeListener deviceSynchronizeListener) {
+ this.deviceSynchronizedListeners.add(deviceSynchronizeListener);
+ }
+
+ @Override
+ public void notifyDeviceSynchronizeListeners(final DeviceInfo deviceInfo, final boolean deviceSynchronized) {
+ for (DeviceSynchronizeListener listener : deviceSynchronizedListeners) {
+ listener.deviceIsSynchronized(deviceInfo, deviceSynchronized);
+ }
+ }
+
+ @Override
+ public void addDeviceValidListener(final DeviceValidListener deviceValidListener) {
+ this.deviceValidListeners.add(deviceValidListener);
+ }
+
+ @Override
+ public void notifyDeviceValidListeners(final DeviceInfo deviceInfo, final boolean deviceValid) {
+ for (DeviceValidListener listener : deviceValidListeners) {
+ listener.deviceIsValid(deviceInfo, deviceValid);
+ }
+ }
+
+ private ListenableFuture<Void> onDeviceTakeClusterLeadership(final DeviceInfo deviceInfo) {
+ LOG.trace("onDeviceTakeClusterLeadership for node: {}", deviceInfo.getNodeId());
+ /* validation */
+ StatisticsContext statisticsContext = conductor.getStatisticsContext(deviceInfo);
+ if (statisticsContext == null) {
+ final String errMsg = String.format("DeviceCtx %s is up but we are missing StatisticsContext", deviceInfo.getDatapathId());
+ LOG.warn(errMsg);
+ return Futures.immediateFailedFuture(new IllegalStateException(errMsg));
+ }
+ DeviceContext deviceContext = conductor.getDeviceContext(deviceInfo);
+ /* Prepare init info collecting */
+ notifyDeviceSynchronizeListeners(deviceInfo, false);
+ ((DeviceContextImpl)deviceContext).getTransactionChainManager().activateTransactionManager();
+ /* Init Collecting NodeInfo */
+ final ListenableFuture<Void> initCollectingDeviceInfo = DeviceInitializationUtils.initializeNodeInformation(
+ deviceContext, switchFeaturesMandatory);
+ /* Init Collecting StatInfo */
+ final ListenableFuture<Boolean> statPollFuture = Futures.transform(initCollectingDeviceInfo,
+ new AsyncFunction<Void, Boolean>() {
+
+ @Override
+ public ListenableFuture<Boolean> apply(@Nonnull final Void input) throws Exception {
+ statisticsContext.statListForCollectingInitialization();
+ return statisticsContext.initialGatherDynamicData();
+ }
+ });
+
+ return Futures.transform(statPollFuture, new Function<Boolean, Void>() {
+
+ @Override
+ public Void apply(final Boolean input) {
+ if (ConnectionContext.CONNECTION_STATE.RIP.equals(conductor.gainConnectionStateSafely(deviceInfo))) {
+ final String errMsg = String.format("We lost connection for Device %s, context has to be closed.",
+ deviceInfo.getNodeId());
+ LOG.warn(errMsg);
+ throw new IllegalStateException(errMsg);
+ }
+ if (!input) {
+ final String errMsg = String.format("Get Initial Device %s information fails",
+ deviceInfo.getNodeId());
+ LOG.warn(errMsg);
+ throw new IllegalStateException(errMsg);
+ }
+ LOG.debug("Get Initial Device {} information is successful", deviceInfo.getNodeId());
+ notifyDeviceSynchronizeListeners(deviceInfo, true);
+ ((DeviceContextImpl)deviceContext).getTransactionChainManager().initialSubmitWriteTransaction();
+ deviceContext.getDeviceState().setStatisticsPollingEnabledProp(true);
+ return null;
+ }
+ });
+ }
+
}
package org.opendaylight.openflowplugin.impl.device;
-import com.google.common.base.Preconditions;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
-import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
/**
* openflowplugin-impl
* DeviceState is builded from {@link FeaturesReply} and {@link NodeId}. Both values are inside
* {@link org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext}
*
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- * <p/>
- * Created: Mar 29, 2015
*/
class DeviceStateImpl implements DeviceState {
- private final GetFeaturesOutput featuresOutput;
- private final NodeId nodeId;
- private final KeyedInstanceIdentifier<Node, NodeKey> nodeII;
- private final short version;
+ private final DeviceInfo deviceInfo;
private boolean valid;
private boolean meterIsAvailable;
private boolean groupIsAvailable;
private boolean statPollEnabled;
private boolean queueStatisticsAvailable;
- public DeviceStateImpl(@CheckForNull final FeaturesReply featuresReply, @Nonnull final NodeId nodeId) {
- Preconditions.checkArgument(featuresReply != null);
- featuresOutput = new GetFeaturesOutputBuilder(featuresReply).build();
- this.nodeId = Preconditions.checkNotNull(nodeId);
- nodeII = DeviceStateUtil.createNodeInstanceIdentifier(nodeId);
- version = featuresReply.getVersion();
+ public DeviceStateImpl(final DeviceInfo deviceInfo) {
+ this.deviceInfo = deviceInfo;
statPollEnabled = false;
deviceSynchronized = false;
}
- @Override
- public NodeId getNodeId() {
- return nodeId;
- }
-
- @Override
- public KeyedInstanceIdentifier<Node, NodeKey> getNodeInstanceIdentifier() {
- return nodeII;
- }
-
- @Override
- public GetFeaturesOutput getFeatures() {
- return featuresOutput;
- }
-
@Override
public boolean isValid() {
return valid;
}
- @Override
- public void setValid(final boolean valid) {
- this.valid = valid;
- }
-
- @Override
- public short getVersion() {
- return version;
- }
-
@Override
public boolean isMetersAvailable() {
return meterIsAvailable;
}
- @Override
- public void setDeviceSynchronized(final boolean _deviceSynchronized) {
- deviceSynchronized = _deviceSynchronized;
- }
-
@Override
public boolean isStatisticsPollingEnabled() {
return statPollEnabled;
public void setStatisticsPollingEnabledProp(final boolean statPollEnabled) {
this.statPollEnabled = statPollEnabled;
}
+
+ @Override
+ public void deviceIsSynchronized(final DeviceInfo deviceInfo, final boolean isSynchronized) {
+ if (this.deviceInfo.equals(deviceInfo)) {
+ this.deviceSynchronized = isSynchronized;
+ }
+ }
+
+ @Override
+ public void deviceIsValid(final DeviceInfo deviceInfo, final boolean isValid) {
+ if (this.deviceInfo.equals(deviceInfo)) {
+ this.valid = isValid;
+ }
+ }
}
import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
private final Object txLock = new Object();
private final KeyedInstanceIdentifier<Node, NodeKey> nodeII;
+ private final DeviceInfo deviceInfo;
private final DataBroker dataBroker;
private final LifecycleConductor conductor;
private TransactionChainManagerStatus transactionChainManagerStatus = TransactionChainManagerStatus.SLEEPING;
TransactionChainManager(@Nonnull final DataBroker dataBroker,
- @Nonnull final DeviceState deviceState,
+ @Nonnull final DeviceInfo deviceInfo,
@Nonnull final LifecycleConductor conductor) {
this.dataBroker = Preconditions.checkNotNull(dataBroker);
this.conductor = Preconditions.checkNotNull(conductor);
- this.nodeII = Preconditions.checkNotNull(deviceState.getNodeInstanceIdentifier());
+ this.deviceInfo = deviceInfo;
+ this.nodeII = deviceInfo.getNodeInstanceIdentifier();
this.transactionChainManagerStatus = TransactionChainManagerStatus.SLEEPING;
lastSubmittedFuture = Futures.immediateFuture(null);
- LOG.debug("created txChainManager for {}", nodeII);
+ LOG.debug("created txChainManager for {}", this.nodeII);
}
private NodeId nodeId() {
* registration for this class instance as {@link TransactionChainListener} to provide possibility a make DS
* transactions. Call this method for MASTER role only.
*/
- public void activateTransactionManager() {
+ void activateTransactionManager() {
LOG.trace("activateTransactionManager for node {} transaction submit is set to {}", nodeId(), submitIsEnabled);
synchronized (txLock) {
if (TransactionChainManagerStatus.SLEEPING.equals(transactionChainManagerStatus)) {
* Call this method for SLAVE only.
* @return Future
*/
- public ListenableFuture<Void> deactivateTransactionManager() {
+ ListenableFuture<Void> deactivateTransactionManager() {
final ListenableFuture<Void> future;
synchronized (txLock) {
if (TransactionChainManagerStatus.WORKING.equals(transactionChainManagerStatus)) {
}
if (initCommit) {
LOG.error("Initial commit failed. {}", t);
- conductor.closeConnection(nodeId());
+ conductor.closeConnection(deviceInfo);
}
}
});
package org.opendaylight.openflowplugin.impl.role;
import com.google.common.base.Preconditions;
-
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-
import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
-import org.opendaylight.openflowplugin.impl.LifecycleConductorImpl;
import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
private static final int TIMEOUT = 12;
- private final NodeId nodeId;
+ private final DeviceInfo deviceInfo;
private final EntityOwnershipService entityOwnershipService;
private volatile EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration = null;
private volatile EntityOwnershipCandidateRegistration txEntityOwnershipCandidateRegistration = null;
private final Semaphore roleChangeGuard = new Semaphore(1, true);
private final LifecycleConductor conductor;
+ private volatile CONTEXT_STATE contextState;
- public RoleContextImpl(final NodeId nodeId, final EntityOwnershipService entityOwnershipService, final Entity entity, final Entity txEntity, final LifecycleConductor lifecycleConductor) {
+ RoleContextImpl(final DeviceInfo deviceInfo, final EntityOwnershipService entityOwnershipService, final Entity entity, final Entity txEntity, final LifecycleConductor lifecycleConductor) {
this.entityOwnershipService = entityOwnershipService;
this.entity = entity;
this.txEntity = txEntity;
- this.nodeId = nodeId;
+ this.deviceInfo = deviceInfo;
this.conductor = lifecycleConductor;
+ contextState = CONTEXT_STATE.INITIALIZATION;
}
@Override
public boolean initialization() {
- LOG.info("Initialization main candidate for node {}", nodeId);
+ LOG.info("Initialization main candidate for node {}", deviceInfo.getNodeId());
+ contextState = CONTEXT_STATE.WORKING;
return registerCandidate(this.entity);
}
@Override
public void unregisterAllCandidates() {
- LOG.info("Role context closed, unregistering all candidates for ownership for node {}", nodeId);
+ LOG.info("Role context closed, unregistering all candidates for ownership for node {}", deviceInfo.getNodeId());
if (isMainCandidateRegistered()) {
unregisterCandidate(this.entity);
}
@Nullable
@Override
public <T> RequestContext<T> createRequestContext() {
- return new AbstractRequestContext<T>(conductor.reserveXidForDeviceMessage(nodeId)) {
+ return new AbstractRequestContext<T>(conductor.reserveXidForDeviceMessage(deviceInfo)) {
@Override
public void close() {
}
}
@Override
- public NodeId getNodeId() {
- return nodeId;
+ public DeviceInfo getDeviceInfo() {
+ return deviceInfo;
}
@Override
@Override
public void close() {
+ contextState = CONTEXT_STATE.TERMINATION;
unregisterAllCandidates();
}
public boolean isMaster(){
return (txEntityOwnershipCandidateRegistration != null && entityOwnershipCandidateRegistration != null);
}
+
+ @Override
+ public CONTEXT_STATE getState() {
+ return contextState;
+ }
}
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.Timeout;
import io.netty.util.TimerTask;
-
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
public class RoleManagerImpl implements RoleManager, EntityOwnershipListener, ServiceChangeListener {
private static final Logger LOG = LoggerFactory.getLogger(RoleManagerImpl.class);
+ // Maximum limit of timeout retries when cleaning DS, to prevent infinite recursive loops
+ private static final int MAX_CLEAN_DS_RETRIES = 3;
+
private DeviceInitializationPhaseHandler deviceInitializationPhaseHandler;
private DeviceTerminationPhaseHandler deviceTerminationPhaseHandler;
private final DataBroker dataBroker;
private final EntityOwnershipService entityOwnershipService;
- private final ConcurrentMap<NodeId, RoleContext> contexts = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceInfo, RoleContext> contexts = new ConcurrentHashMap<>();
private final ConcurrentMap<Entity, RoleContext> watchingEntities = new ConcurrentHashMap<>();
private final EntityOwnershipListenerRegistration entityOwnershipListenerRegistration;
private final EntityOwnershipListenerRegistration txEntityOwnershipListenerRegistration;
}
@Override
- public void onDeviceContextLevelUp(@CheckForNull final NodeId nodeId) throws Exception {
- final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
- final RoleContext roleContext = new RoleContextImpl(nodeId, entityOwnershipService, makeEntity(nodeId), makeTxEntity(nodeId), conductor);
+ public void onDeviceContextLevelUp(@CheckForNull final DeviceInfo deviceInfo) throws Exception {
+ final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(deviceInfo));
+ final RoleContext roleContext = new RoleContextImpl(deviceInfo, entityOwnershipService, makeEntity(deviceInfo.getNodeId()), makeTxEntity(deviceInfo.getNodeId()), conductor);
roleContext.setSalRoleService(new SalRoleServiceImpl(roleContext, deviceContext));
- Verify.verify(contexts.putIfAbsent(nodeId, roleContext) == null, "Role context for master Node %s is still not closed.", nodeId);
+ Verify.verify(contexts.putIfAbsent(deviceInfo, roleContext) == null, "Role context for master Node %s is still not closed.", deviceInfo.getNodeId());
makeDeviceRoleChange(OfpRole.BECOMESLAVE, roleContext, true);
- notifyListenersRoleInitializationDone(roleContext.getNodeId(), roleContext.initialization());
+ /* First start to watch entity so we don't miss any notification, and then try to register in EOS */
watchingEntities.put(roleContext.getEntity(), roleContext);
- deviceInitializationPhaseHandler.onDeviceContextLevelUp(nodeId);
+ notifyListenersRoleInitializationDone(roleContext.getDeviceInfo(), roleContext.initialization());
+ deviceInitializationPhaseHandler.onDeviceContextLevelUp(deviceInfo);
}
@Override
final RoleContext roleContext = iterator.next();
watchingEntities.remove(roleContext.getEntity());
watchingEntities.remove(roleContext.getTxEntity());
- contexts.remove(roleContext.getNodeId());
+ contexts.remove(roleContext.getDeviceInfo());
if (roleContext.isTxCandidateRegistered()) {
LOG.info("Node {} was holder txEntity, so trying to remove device from operational DS.");
- removeDeviceFromOperationalDS(roleContext.getNodeId());
+ removeDeviceFromOperationalDS(roleContext.getDeviceInfo(), MAX_CLEAN_DS_RETRIES);
} else {
roleContext.close();
}
}
@Override
- public void onDeviceContextLevelDown(final DeviceContext deviceContext) {
- final NodeId nodeId = deviceContext.getPrimaryConnectionContext().getNodeId();
- LOG.trace("onDeviceContextLevelDown for node {}", nodeId);
- final RoleContext roleContext = contexts.get(nodeId);
+ public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
+ LOG.trace("onDeviceContextLevelDown for node {}", deviceInfo.getNodeId());
+ final RoleContext roleContext = contexts.get(deviceInfo);
if (roleContext != null) {
- LOG.debug("Found roleContext associated to deviceContext: {}, now trying close the roleContext", nodeId);
+ LOG.debug("Found roleContext associated to deviceContext: {}, now trying close the roleContext", deviceInfo.getNodeId());
if (roleContext.isMainCandidateRegistered()) {
roleContext.unregisterCandidate(roleContext.getEntity());
} else {
- contexts.remove(nodeId, roleContext);
+ contexts.remove(deviceInfo.getNodeId(), roleContext);
roleContext.close();
}
}
- deviceTerminationPhaseHandler.onDeviceContextLevelDown(deviceContext);
+ deviceTerminationPhaseHandler.onDeviceContextLevelDown(deviceInfo);
}
@VisibleForTesting
Preconditions.checkArgument(ownershipChange != null);
final RoleContext roleContext = watchingEntities.get(ownershipChange.getEntity());
- LOG.debug("Received EOS message: wasOwner:{} isOwner:{} hasOwner:{} for entity type {} and node {}",
- ownershipChange.wasOwner(), ownershipChange.isOwner(), ownershipChange.hasOwner(),
+ LOG.debug("Received EOS message: wasOwner:{} isOwner:{} hasOwner:{} inJeopardy:{} for entity type {} and node {}",
+ ownershipChange.wasOwner(), ownershipChange.isOwner(), ownershipChange.hasOwner(), ownershipChange.inJeopardy(),
ownershipChange.getEntity().getType(),
- roleContext != null ? roleContext.getNodeId() : "-> no watching entity, disregarding notification <-");
+ roleContext != null ? roleContext.getDeviceInfo().getNodeId() : "-> no watching entity, disregarding notification <-");
if (roleContext != null) {
if (ownershipChange.getEntity().equals(roleContext.getEntity())) {
if (roleContext.isMainCandidateRegistered()) {
LOG.debug("Main-EntityOwnershipRegistration is active for entity type {} and node {}",
- ownershipChange.getEntity().getType(), roleContext.getNodeId());
- if (!ownershipChange.wasOwner() && ownershipChange.isOwner()) {
+ ownershipChange.getEntity().getType(), roleContext.getDeviceInfo().getNodeId());
+ if (!ownershipChange.wasOwner() && ownershipChange.isOwner() && !ownershipChange.inJeopardy()) {
// SLAVE -> MASTER
- LOG.debug("SLAVE to MASTER for node {}", roleContext.getNodeId());
+ LOG.debug("SLAVE to MASTER for node {}", roleContext.getDeviceInfo().getNodeId());
if (roleContext.registerCandidate(roleContext.getTxEntity())) {
- LOG.debug("Starting watching tx entity for node {}", roleContext.getNodeId());
+ LOG.debug("Starting watching tx entity for node {}", roleContext.getDeviceInfo().getNodeId());
watchingEntities.putIfAbsent(roleContext.getTxEntity(), roleContext);
}
- } else if (ownershipChange.wasOwner() && !ownershipChange.isOwner()) {
+ } else if ((ownershipChange.wasOwner() && !ownershipChange.isOwner()) || (ownershipChange.inJeopardy())) {
// MASTER -> SLAVE
- LOG.debug("MASTER to SLAVE for node {}", roleContext.getNodeId());
- conductor.addOneTimeListenerWhenServicesChangesDone(this, roleContext.getNodeId());
+ LOG.debug("MASTER to SLAVE for node {}", roleContext.getDeviceInfo().getNodeId());
+ conductor.addOneTimeListenerWhenServicesChangesDone(this, roleContext.getDeviceInfo());
makeDeviceRoleChange(OfpRole.BECOMESLAVE, roleContext, false);
}
} else {
LOG.debug("Main-EntityOwnershipRegistration is not active for entity type {} and node {}",
- ownershipChange.getEntity(), roleContext.getNodeId());
+ ownershipChange.getEntity(), roleContext.getDeviceInfo().getNodeId());
watchingEntities.remove(ownershipChange.getEntity(), roleContext);
if (roleContext.isTxCandidateRegistered()) {
- LOG.debug("tx candidate still registered for node {}, probably connection lost, trying to unregister tx candidate", roleContext.getNodeId());
+ LOG.debug("tx candidate still registered for node {}, probably connection lost, trying to unregister tx candidate", roleContext.getDeviceInfo().getNodeId());
roleContext.unregisterCandidate(roleContext.getTxEntity());
if (ownershipChange.wasOwner() && !ownershipChange.isOwner() && !ownershipChange.hasOwner()) {
- LOG.debug("Trying to remove from operational node: {}", roleContext.getNodeId());
- removeDeviceFromOperationalDS(roleContext.getNodeId());
+ LOG.debug("Trying to remove from operational node: {}", roleContext.getDeviceInfo().getNodeId());
+ removeDeviceFromOperationalDS(roleContext.getDeviceInfo(), MAX_CLEAN_DS_RETRIES);
}
} else {
- final NodeId nodeId = roleContext.getNodeId();
- contexts.remove(nodeId, roleContext);
+ contexts.remove(roleContext.getDeviceInfo(), roleContext);
roleContext.close();
- conductor.closeConnection(nodeId);
+ conductor.closeConnection(roleContext.getDeviceInfo());
}
}
}
if (roleContext.isTxCandidateRegistered()) {
LOG.debug("Tx-EntityOwnershipRegistration is active for entity type {} and node {}",
ownershipChange.getEntity().getType(),
- roleContext.getNodeId());
- if (!ownershipChange.wasOwner() && ownershipChange.isOwner()) {
- // SLAVE -> MASTER
- LOG.debug("SLAVE to MASTER for node {}", roleContext.getNodeId());
- makeDeviceRoleChange(OfpRole.BECOMEMASTER, roleContext,false);
- } else if (ownershipChange.wasOwner() && !ownershipChange.isOwner()) {
- // MASTER -> SLAVE
- LOG.debug("MASTER to SLAVE for node {}", roleContext.getNodeId());
- LOG.warn("Tx-EntityOwnershipRegistration lost leadership entity type {} and node {}",
- ownershipChange.getEntity().getType(),roleContext.getNodeId());
- watchingEntities.remove(roleContext.getTxEntity(), roleContext);
- watchingEntities.remove(roleContext.getEntity(), roleContext);
- roleContext.unregisterCandidate(roleContext.getEntity());
+ roleContext.getDeviceInfo().getNodeId());
+ if (ownershipChange.inJeopardy()) {
+ LOG.warn("Getting 'inJeopardy' flag from EOS. Removing txCandidate and stopping watching txCandidate.");
+ watchingEntities.remove(roleContext.getTxEntity());
roleContext.unregisterCandidate(roleContext.getTxEntity());
- if (!ownershipChange.hasOwner()) {
- LOG.debug("Trying to remove from operational node: {}", roleContext.getNodeId());
- removeDeviceFromOperationalDS(roleContext.getNodeId());
- } else {
- final NodeId nodeId = roleContext.getNodeId();
- contexts.remove(nodeId, roleContext);
- roleContext.close();
- conductor.closeConnection(nodeId);
+ } else {
+ if (!ownershipChange.wasOwner() && ownershipChange.isOwner()) {
+ // SLAVE -> MASTER
+ LOG.debug("SLAVE to MASTER for node {}", roleContext.getDeviceInfo().getNodeId());
+ makeDeviceRoleChange(OfpRole.BECOMEMASTER, roleContext, false);
+ } else if (ownershipChange.wasOwner() && !ownershipChange.isOwner()) {
+ // MASTER -> SLAVE
+ LOG.debug("MASTER to SLAVE for node {}", roleContext.getDeviceInfo().getNodeId());
+ LOG.warn("Tx-EntityOwnershipRegistration lost leadership entity type {} and node {}",
+ ownershipChange.getEntity().getType(), roleContext.getDeviceInfo().getNodeId());
+ watchingEntities.remove(roleContext.getTxEntity(), roleContext);
+ watchingEntities.remove(roleContext.getEntity(), roleContext);
+ roleContext.unregisterCandidate(roleContext.getEntity());
+ roleContext.unregisterCandidate(roleContext.getTxEntity());
+ if (!ownershipChange.hasOwner()) {
+ LOG.debug("Trying to remove from operational node: {}", roleContext.getDeviceInfo().getNodeId());
+ removeDeviceFromOperationalDS(roleContext.getDeviceInfo(), MAX_CLEAN_DS_RETRIES);
+ } else {
+ final NodeId nodeId = roleContext.getDeviceInfo().getNodeId();
+ contexts.remove(roleContext.getDeviceInfo(), roleContext);
+ roleContext.close();
+ conductor.closeConnection(roleContext.getDeviceInfo());
+ }
}
}
} else {
- LOG.debug("Tx-EntityOwnershipRegistration is not active for entity {}", ownershipChange.getEntity().getType());
+ LOG.debug("Tx-EntityOwnershipRegistration is not active for entity type {} and node {}", ownershipChange.getEntity().getType(), roleContext.getDeviceInfo().getNodeId());
watchingEntities.remove(roleContext.getTxEntity(), roleContext);
- final NodeId nodeId = roleContext.getNodeId();
- contexts.remove(nodeId, roleContext);
+ contexts.remove(roleContext.getDeviceInfo(), roleContext);
roleContext.close();
- conductor.closeConnection(nodeId);
+ conductor.closeConnection(roleContext.getDeviceInfo());
}
}
Futures.addCallback(roleChangeFuture, new FutureCallback<RpcResult<SetRoleOutput>>() {
@Override
public void onSuccess(@Nullable final RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
- LOG.info("Role {} successfully set on device {}", role, roleContext.getNodeId());
- notifyListenersRoleChangeOnDevice(roleContext.getNodeId(), true, role, init);
+ LOG.info("Role {} successfully set on device {}", role, roleContext.getDeviceInfo().getNodeId());
+ notifyListenersRoleChangeOnDevice(roleContext.getDeviceInfo(), true, role, init);
}
@Override
public void onFailure(@Nonnull final Throwable throwable) {
- LOG.warn("Unable to set role {} on device {}", role, roleContext.getNodeId());
- notifyListenersRoleChangeOnDevice(roleContext.getNodeId(), false, role, init);
+ LOG.warn("Unable to set role {} on device {}", role, roleContext.getDeviceInfo().getNodeId());
+ notifyListenersRoleChangeOnDevice(roleContext.getDeviceInfo(), false, role, init);
}
});
}
@VisibleForTesting
ListenableFuture<RpcResult<SetRoleOutput>> sendRoleChangeToDevice(final OfpRole newRole, final RoleContext roleContext) {
- LOG.debug("Sending new role {} to device {}", newRole, roleContext.getNodeId());
+ LOG.debug("Sending new role {} to device {}", newRole, roleContext.getDeviceInfo().getNodeId());
final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture;
- final Short version = conductor.gainVersionSafely(roleContext.getNodeId());
+ final Short version = roleContext.getDeviceInfo().getVersion();
if (null == version) {
LOG.debug("Device version is null");
return Futures.immediateFuture(null);
return Futures.immediateFuture(null);
} else {
final SetRoleInput setRoleInput = (new SetRoleInputBuilder()).setControllerRole(newRole)
- .setNode(new NodeRef(DeviceStateUtil.createNodeInstanceIdentifier(roleContext.getNodeId()))).build();
+ .setNode(new NodeRef(DeviceStateUtil.createNodeInstanceIdentifier(roleContext.getDeviceInfo().getNodeId()))).build();
setRoleOutputFuture = roleContext.getSalRoleService().setRole(setRoleInput);
- final TimerTask timerTask = new TimerTask() {
-
- @Override
- public void run(final Timeout timeout) throws Exception {
- if (!setRoleOutputFuture.isDone()) {
- LOG.warn("New role {} was not propagated to device {} during 10 sec", newRole, roleContext.getNodeId());
- setRoleOutputFuture.cancel(true);
- }
+ final TimerTask timerTask = timeout -> {
+ if (!setRoleOutputFuture.isDone()) {
+ LOG.warn("New role {} was not propagated to device {} during 10 sec", newRole, roleContext.getDeviceInfo().getNodeId());
+ setRoleOutputFuture.cancel(true);
}
};
conductor.newTimeout(timerTask, 10, TimeUnit.SECONDS);
}
@VisibleForTesting
- CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(final NodeId nodeId) {
-
+ CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(final DeviceInfo deviceInfo, final int numRetries) {
final WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction();
- delWtx.delete(LogicalDatastoreType.OPERATIONAL, DeviceStateUtil.createNodeInstanceIdentifier(nodeId));
+ delWtx.delete(LogicalDatastoreType.OPERATIONAL, DeviceStateUtil.createNodeInstanceIdentifier(deviceInfo.getNodeId()));
final CheckedFuture<Void, TransactionCommitFailedException> delFuture = delWtx.submit();
- Futures.addCallback(delFuture, new FutureCallback<Void>() {
+ Futures.addCallback(delFuture, new FutureCallback<Void>() {
@Override
public void onSuccess(final Void result) {
- LOG.debug("Delete Node {} was successful", nodeId);
- final RoleContext roleContext = contexts.remove(nodeId);
+ LOG.debug("Delete Node {} was successful", deviceInfo);
+ final RoleContext roleContext = contexts.remove(deviceInfo);
if (roleContext != null) {
roleContext.close();
}
@Override
public void onFailure(@Nonnull final Throwable t) {
- LOG.warn("Delete Node {} failed. {}", nodeId, t);
- contexts.remove(nodeId);
- final RoleContext roleContext = contexts.remove(nodeId);
+ // If we have any retries left, we will try to clean the datastore again
+ if (numRetries > 0) {
+ // We "used" one retry here, so decrement it
+ final int curRetries = numRetries - 1;
+ LOG.debug("Delete node {} failed with exception {}. Trying again (retries left: {})", deviceInfo.getNodeId(), t, curRetries);
+ // Recursive call to this method with "one less" retry
+ removeDeviceFromOperationalDS(deviceInfo, curRetries);
+ return;
+ }
+
+ // No retries left, so we will just close the role context, and ignore datastore cleanup
+ LOG.warn("Delete node {} failed with exception {}. No retries left, aborting", deviceInfo.getNodeId(), t);
+ final RoleContext roleContext = contexts.remove(deviceInfo);
if (roleContext != null) {
roleContext.close();
}
}
});
+
return delFuture;
}
}
@Override
- public void servicesChangeDone(final NodeId nodeId, final boolean success) {
- LOG.debug("Services stopping done for node {} as " + (success ? "successful" : "unsuccessful"), nodeId);
- final RoleContext roleContext = contexts.get(nodeId);
+ public void servicesChangeDone(final DeviceInfo deviceInfo, final boolean success) {
+ LOG.debug("Services stopping done for node {} as " + (success ? "successful" : "unsuccessful"), deviceInfo);
+ final RoleContext roleContext = contexts.get(deviceInfo);
if (null != roleContext) {
/* Services stopped or failure */
roleContext.unregisterCandidate(roleContext.getTxEntity());
}
@VisibleForTesting
- RoleContext getRoleContext(final NodeId nodeId){
- return contexts.get(nodeId);
+ RoleContext getRoleContext(final DeviceInfo deviceInfo){
+ return contexts.get(deviceInfo);
}
/**
* This method is only for testing
*/
@VisibleForTesting
- void setRoleContext(NodeId nodeId, RoleContext roleContext){
- if(!contexts.containsKey(nodeId)) {
- contexts.put(nodeId, roleContext);
+ void setRoleContext(DeviceInfo deviceInfo, RoleContext roleContext){
+ if(!contexts.containsKey(deviceInfo)) {
+ contexts.put(deviceInfo, roleContext);
}
}
/**
* Invoked when initialization phase is done
- * @param nodeId node identification
+ * @param deviceInfo node identification
* @param success true if initialization done ok, false otherwise
*/
@VisibleForTesting
- void notifyListenersRoleInitializationDone(final NodeId nodeId, final boolean success){
+ void notifyListenersRoleInitializationDone(final DeviceInfo deviceInfo, final boolean success){
LOG.debug("Notifying registered listeners for role initialization done, no. of listeners {}", listeners.size());
for (final RoleChangeListener listener : listeners) {
- listener.roleInitializationDone(nodeId, success);
+ listener.roleInitializationDone(deviceInfo, success);
}
}
/**
* Notifies registered listener on role change. Role is the new role on device
* If initialization phase is true, we may skip service starting
+ * @param deviceInfo
* @param success true if role change on device done ok, false otherwise
* @param role new role meant to be set on device
* @param initializationPhase if true, then skipp services start
*/
@VisibleForTesting
- void notifyListenersRoleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole role, final boolean initializationPhase){
+ void notifyListenersRoleChangeOnDevice(final DeviceInfo deviceInfo, final boolean success, final OfpRole role, final boolean initializationPhase){
LOG.debug("Notifying registered listeners for role change, no. of listeners {}", listeners.size());
for (final RoleChangeListener listener : listeners) {
- listener.roleChangeOnDevice(nodeId, success, role, initializationPhase);
+ listener.roleChangeOnDevice(deviceInfo, success, role, initializationPhase);
}
}
+ @Override
+ public <T extends OFPContext> T gainContext(DeviceInfo deviceInfo) {
+ return (T) contexts.get(deviceInfo);
+ }
}
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Semaphore;
-
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.XidSequencer;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class RpcContextImpl implements RpcContext {
+class RpcContextImpl implements RpcContext {
private static final Logger LOG = LoggerFactory.getLogger(RpcContextImpl.class);
private final RpcProviderRegistry rpcProviderRegistry;
private final MessageSpy messageSpy;
private final Semaphore tracker;
private final XidSequencer xidSequencer;
+ private boolean isStatisticsRpcEnabled;
+
+ private volatile CONTEXT_STATE contextState;
// TODO: add private Sal salBroker
private final ConcurrentMap<Class<?>, RoutedRpcRegistration<?>> rpcRegistrations = new ConcurrentHashMap<>();
private final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
- public RpcContextImpl(final RpcProviderRegistry rpcProviderRegistry,
+ RpcContextImpl(final RpcProviderRegistry rpcProviderRegistry,
final XidSequencer xidSequencer,
final MessageSpy messageSpy,
final int maxRequests,
this.nodeInstanceIdentifier = nodeInstanceIdentifier;
tracker = new Semaphore(maxRequests, true);
+ contextState = CONTEXT_STATE.WORKING;
}
/**
*/
@Override
public void close() {
- for (final Iterator<Entry<Class<?>, RoutedRpcRegistration<?>>> iterator = Iterators
- .consumingIterator(rpcRegistrations.entrySet().iterator()); iterator.hasNext();) {
- final RoutedRpcRegistration<?> rpcRegistration = iterator.next().getValue();
- rpcRegistration.unregisterPath(NodeContext.class, nodeInstanceIdentifier);
- rpcRegistration.close();
- LOG.debug("Closing RPC Registration of service {} for device {}.", rpcRegistration.getServiceType(),
- nodeInstanceIdentifier);
+ if (CONTEXT_STATE.TERMINATION.equals(contextState)){
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("RpcContext is already in TERMINATION state.");
+ }
+ } else {
+ contextState = CONTEXT_STATE.TERMINATION;
+ for (final Iterator<Entry<Class<?>, RoutedRpcRegistration<?>>> iterator = Iterators
+ .consumingIterator(rpcRegistrations.entrySet().iterator()); iterator.hasNext(); ) {
+ final RoutedRpcRegistration<?> rpcRegistration = iterator.next().getValue();
+ rpcRegistration.unregisterPath(NodeContext.class, nodeInstanceIdentifier);
+ rpcRegistration.close();
+ LOG.debug("Closing RPC Registration of service {} for device {}.", rpcRegistration.getServiceType(),
+ nodeInstanceIdentifier);
+ }
}
}
}
@VisibleForTesting
- public boolean isEmptyRpcRegistrations() {
+ boolean isEmptyRpcRegistrations() {
return this.rpcRegistrations.isEmpty();
}
+ @Override
+ public void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled) {
+ this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
+ }
+ @Override
+ public boolean isStatisticsRpcEnabled() {
+ return isStatisticsRpcEnabled;
+ }
+
+ @Override
+ public CONTEXT_STATE getState() {
+ return contextState;
+ }
}
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
private final int maxRequestsQuota;
- private final ConcurrentMap<NodeId, RpcContext> contexts = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceInfo, RpcContext> contexts = new ConcurrentHashMap<>();
+ private boolean isStatisticsRpcEnabled;
private final LifecycleConductor conductor;
}
@Override
- public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
+ public void onDeviceContextLevelUp(final DeviceInfo deviceInfo) throws Exception {
- final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
+ final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(deviceInfo));
final RpcContext rpcContext = new RpcContextImpl(
rpcProviderRegistry,
deviceContext,
deviceContext.getMessageSpy(),
maxRequestsQuota,
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ deviceInfo.getNodeInstanceIdentifier());
- deviceContext.setRpcContext(rpcContext);
+ Verify.verify(contexts.putIfAbsent(deviceInfo, rpcContext) == null, "RpcCtx still not closed for node {}", deviceInfo.getNodeId());
- Verify.verify(contexts.putIfAbsent(nodeId, rpcContext) == null, "RpcCtx still not closed for node {}", nodeId);
+ rpcContext.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
// finish device initialization cycle back to DeviceManager
- deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
+ deviceInitPhaseHandler.onDeviceContextLevelUp(deviceInfo);
}
@Override
}
@Override
- public void onDeviceContextLevelDown(final DeviceContext deviceContext) {
- final RpcContext removedContext = contexts.remove(deviceContext.getDeviceState().getNodeId());
+ public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
+ final RpcContext removedContext = contexts.remove(deviceInfo);
if (removedContext != null) {
LOG.info("Unregister RPCs services for device context closure");
removedContext.close();
}
- deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceContext);
+ deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
}
@Override
* This method is only for testing
*/
@VisibleForTesting
- void addRecordToContexts(NodeId nodeId, RpcContext rpcContexts) {
- if(!contexts.containsKey(nodeId)) {
- this.contexts.put(nodeId,rpcContexts);
+ void addRecordToContexts(DeviceInfo deviceInfo, RpcContext rpcContexts) {
+ if(!contexts.containsKey(deviceInfo)) {
+ this.contexts.put(deviceInfo,rpcContexts);
}
}
+
+ @Override
+ public <T extends OFPContext> T gainContext(DeviceInfo deviceInfo) {
+ return (T) contexts.get(deviceInfo);
+ }
+
+
+ @Override
+ public void setStatisticsRpcEnabled(boolean statisticsRpcEnabled) {
+ isStatisticsRpcEnabled = statisticsRpcEnabled;
+ }
}
@Override
protected final FutureCallback<OfHeader> createCallback(final RequestContext<List<MultipartReply>> context, final Class<?> requestType) {
return new MultipartRequestOnTheFlyCallback(context, requestType,
- getDeviceContext().getMessageSpy(), getEventIdentifier(), getDeviceContext().getDeviceState(),
- getDeviceContext().getDeviceFlowRegistry(), getDeviceContext());
+ getMessageSpy(), getEventIdentifier(), getDeviceInfo(),
+ getDeviceContext().getDeviceFlowRegistry(), getTxFacade());
}
import javax.annotation.Nonnull;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceRegistry;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
import org.opendaylight.openflowplugin.api.openflow.device.Xid;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.common.RpcError;
private final RequestContextStack requestContextStack;
private final DeviceContext deviceContext;
private final MessageSpy messageSpy;
- private final NodeId nodeId;
private EventIdentifier eventIdentifier;
- public AbstractService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
- final DeviceState deviceState = deviceContext.getDeviceState();
- final GetFeaturesOutput features = deviceState.getFeatures();
+ AbstractService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
+ final DeviceInfo deviceInfo = deviceContext.getDeviceInfo();
this.requestContextStack = requestContextStack;
this.deviceContext = deviceContext;
- this.datapathId = features.getDatapathId();
- this.version = features.getVersion();
+ this.datapathId = deviceInfo.getDatapathId();
+ this.version = deviceInfo.getVersion();
this.messageSpy = deviceContext.getMessageSpy();
- this.nodeId = deviceState.getNodeId();
}
public EventIdentifier getEventIdentifier() {
return datapathId;
}
- public NodeId getNodeId() {
- return nodeId;
- }
-
public RequestContextStack getRequestContextStack() {
return requestContextStack;
}
+ @Deprecated
public DeviceContext getDeviceContext() {
return deviceContext;
}
+ protected DeviceRegistry getDeviceRegistry() {return deviceContext;}
+
+ public DeviceInfo getDeviceInfo() {return deviceContext.getDeviceInfo();}
+
+ public TxFacade getTxFacade() {return deviceContext;}
+
public MessageSpy getMessageSpy() {
return messageSpy;
}
import com.google.common.util.concurrent.ListenableFuture;
import java.util.Collections;
import java.util.List;
-
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
final class MultipartRequestOnTheFlyCallback extends AbstractRequestCallback<List<MultipartReply>> {
private static final Logger LOG = LoggerFactory.getLogger(MultipartRequestOnTheFlyCallback.class);
private static final SinglePurposeMultipartReplyTranslator MULTIPART_REPLY_TRANSLATOR = new SinglePurposeMultipartReplyTranslator();
- private final DeviceState deviceState;
+ private final DeviceInfo deviceInfo;
private final DeviceFlowRegistry registry;
private boolean virgin = true;
private boolean finished = false;
final Class<?> requestType,
final MessageSpy messageSpy,
final EventIdentifier eventIdentifier,
- final DeviceState deviceState,
+ final DeviceInfo deviceInfo,
final DeviceFlowRegistry registry,
final TxFacade txFacade) {
super(context, requestType, messageSpy, eventIdentifier);
- this.deviceState = deviceState;
+ this.deviceInfo = deviceInfo;
this.registry = registry;
this.txFacade = txFacade;
//TODO: this is focused on flow stats only - need more general approach if used for more than flow stats
- doneEventIdentifier = new EventIdentifier(MultipartType.OFPMPFLOW.name(), deviceState.getNodeId().toString());
+ doneEventIdentifier = new EventIdentifier(MultipartType.OFPMPFLOW.name(), deviceInfo.getNodeId().toString());
}
public EventIdentifier getDoneEventIdentifier() {
final MultipartReply singleReply = multipartReply;
final List<? extends DataObject> multipartDataList = MULTIPART_REPLY_TRANSLATOR.translate(
- deviceState.getFeatures().getDatapathId(), deviceState.getFeatures().getVersion(), singleReply);
+ deviceInfo.getDatapathId(), deviceInfo.getVersion(), singleReply);
final Iterable<? extends DataObject> allMultipartData = multipartDataList;
//TODO: following part is focused on flow stats only - need more general approach if used for more than flow stats
ListenableFuture<Void> future;
if (virgin) {
- future = StatisticsGatheringUtils.deleteAllKnownFlows(deviceState, registry, txFacade);
+ future = StatisticsGatheringUtils.deleteAllKnownFlows(deviceInfo, registry, txFacade);
virgin = false;
} else {
future = Futures.immediateFuture(null);
@Override
public Void apply(final Void input) {
StatisticsGatheringUtils.writeFlowStatistics((Iterable<FlowsStatisticsUpdate>) allMultipartData,
- deviceState, registry, txFacade);
+ deviceInfo, registry, txFacade);
if (!multipartReply.getFlags().isOFPMPFREQMORE()) {
endCollecting();
EventsTimeCounter.markEnd(getEventIdentifier());
final RpcResult<List<MultipartReply>> rpcResult = RpcResultBuilder.success(Collections.<MultipartReply>emptyList()).build();
spyMessage(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_TRANSLATE_OUT_SUCCESS);
- setResult(rpcResult);
txFacade.submitTransaction();
+ setResult(rpcResult);
finished = true;
}
}
import org.opendaylight.openflowplugin.api.openflow.device.Xid;
import org.opendaylight.openflowplugin.impl.role.RoleChangeException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInputBuilder;
}
public Future<BigInteger> getGenerationIdFromDevice(final Short version) {
- LOG.info("getGenerationIdFromDevice called for device:{}", getNodeId().getValue());
+ LOG.info("getGenerationIdFromDevice called for device:{}", getDeviceInfo().getNodeId().getValue());
// send a dummy no-change role request to get the generation-id of the switch
final RoleRequestInputBuilder roleRequestInputBuilder = new RoleRequestInputBuilder();
finalFuture.set(roleRequestOutput.getGenerationId());
} else {
LOG.info("roleRequestOutput is null in getGenerationIdFromDevice");
- finalFuture.setException(new RoleChangeException("Exception in getting generationId for device:" + getNodeId().getValue()));
+ finalFuture.setException(new RoleChangeException("Exception in getting generationId for device:" + getDeviceInfo().getNodeId().getValue()));
}
} else {
public Future<RpcResult<SetRoleOutput>> submitRoleChange(final OfpRole ofpRole, final Short version, final BigInteger generationId) {
LOG.info("submitRoleChange called for device:{}, role:{}",
- getNodeId(), ofpRole);
+ getDeviceInfo().getNodeId(), ofpRole);
final RoleRequestInputBuilder roleRequestInputBuilder = new RoleRequestInputBuilder();
roleRequestInputBuilder.setRole(toOFJavaRole(ofpRole));
roleRequestInputBuilder.setVersion(version);
@Override
public void onSuccess(final RpcResult<RoleRequestOutput> roleRequestOutputRpcResult) {
LOG.info("submitRoleChange onSuccess for device:{}, role:{}",
- getNodeId(), ofpRole);
+ getDeviceInfo().getNodeId(), ofpRole);
final RoleRequestOutput roleRequestOutput = roleRequestOutputRpcResult.getResult();
final Collection<RpcError> rpcErrors = roleRequestOutputRpcResult.getErrors();
if (roleRequestOutput != null) {
@Override
public void onFailure(final Throwable throwable) {
LOG.error("submitRoleChange onFailure for device:{}, role:{}",
- getNodeId(), ofpRole, throwable);
+ getDeviceInfo().getNodeId(), ofpRole, throwable);
finalFuture.setException(throwable);
}
});
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.device.Xid;
import org.opendaylight.openflowplugin.extension.api.ConvertorMessageToOFJava;
-import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderKeeper;
import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
import org.opendaylight.openflowplugin.extension.api.exception.ConverterNotFoundException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.SalExperimenterMessageService;
public class SalExperimenterMessageServiceImpl extends AbstractVoidService<SendExperimenterInput> implements SalExperimenterMessageService {
- public SalExperimenterMessageServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
+ private final ExtensionConverterProvider extensionConverterProvider;
+
+ public SalExperimenterMessageServiceImpl(final RequestContextStack requestContextStack,
+ final DeviceContext deviceContext,
+ final ExtensionConverterProvider extensionConverterProvider) {
super(requestContextStack, deviceContext);
+ this.extensionConverterProvider = extensionConverterProvider;
}
@Override
protected OfHeader buildRequest(Xid xid, SendExperimenterInput input) throws ConversionException {
final TypeVersionKey key = new TypeVersionKey(input.getExperimenterMessageOfChoice().getImplementedInterface(), getVersion());
final ConvertorMessageToOFJava<ExperimenterMessageOfChoice, ExperimenterDataOfChoice> messageConverter =
- ((ExtensionConverterProviderKeeper) getDeviceContext())
- .getExtensionConverterProvider().getMessageConverter(key);
+ extensionConverterProvider.getMessageConverter(key);
if (messageConverter == null) {
throw new ConverterNotFoundException(key.toString());
}
if (itemLifecycleListener != null) {
KeyedInstanceIdentifier<Flow, FlowKey> flowPath = createFlowPath(flowDescriptor,
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
final FlowBuilder flowBuilder = new FlowBuilder(input).setId(flowDescriptor.getFlowId());
itemLifecycleListener.onAdded(flowPath, flowBuilder.build());
}
deviceContext.getDeviceFlowRegistry().retrieveIdForFlow(flowRegistryKey);
if (flowDescriptor != null) {
KeyedInstanceIdentifier<Flow, FlowKey> flowPath = createFlowPath(flowDescriptor,
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
itemLifecycleListener.onRemoved(flowPath);
}
}
final FlowDescriptor flowDescriptor = deviceContext.getDeviceFlowRegistry().retrieveIdForFlow(flowRegistryKey);
if (flowDescriptor != null) {
KeyedInstanceIdentifier<Flow, FlowKey> flowPath = createFlowPath(flowDescriptor,
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
itemLifecycleListener.onRemoved(flowPath);
}
}
if (itemLifecycleListener != null) {
KeyedInstanceIdentifier<Flow, FlowKey> flowPath = createFlowPath(flowDescriptor,
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
final FlowBuilder flowBuilder = new FlowBuilder(input.getUpdatedFlow()).setId(flowDescriptor.getFlowId());
itemLifecycleListener.onAdded(flowPath, flowBuilder.build());
}
*/
package org.opendaylight.openflowplugin.impl.services;
-import java.util.Collection;
-import java.util.concurrent.Future;
-
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import java.util.concurrent.Future;
+import javax.annotation.Nullable;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
-import org.opendaylight.openflowplugin.impl.registry.flow.FlowDescriptorFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.Nullable;
-
public class SalGroupServiceImpl implements SalGroupService, ItemLifeCycleSource {
private static final Logger LOG = LoggerFactory.getLogger(SalGroupServiceImpl.class);
private final GroupService<AddGroupInput, AddGroupOutput> addGroup;
@Override
public Future<RpcResult<AddGroupOutput>> addGroup(final AddGroupInput input) {
- addGroup.getDeviceContext().getDeviceGroupRegistry().store(input.getGroupId());
+ addGroup.getDeviceRegistry().getDeviceGroupRegistry().store(input.getGroupId());
final ListenableFuture<RpcResult<AddGroupOutput>> resultFuture = addGroup.handleServiceCall(input);
Futures.addCallback(resultFuture, new FutureCallback<RpcResult<AddGroupOutput>>() {
@Override
@Override
public Future<RpcResult<RemoveGroupOutput>> removeGroup(final RemoveGroupInput input) {
- removeGroup.getDeviceContext().getDeviceGroupRegistry().markToBeremoved(input.getGroupId());
+ removeGroup.getDeviceRegistry().getDeviceGroupRegistry().markToBeremoved(input.getGroupId());
final ListenableFuture<RpcResult<RemoveGroupOutput>> resultFuture = removeGroup.handleServiceCall(input);
Futures.addCallback(resultFuture, new FutureCallback<RpcResult<RemoveGroupOutput>>() {
@Override
if (itemLifecycleListener != null) {
KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group, GroupKey> groupPath
= createGroupPath(groupId,
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
itemLifecycleListener.onRemoved(groupPath);
}
}
if (itemLifecycleListener != null) {
KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group, GroupKey> groupPath
= createGroupPath(groupId,
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
itemLifecycleListener.onAdded(groupPath, new GroupBuilder(data).build());
}
}
*/
package org.opendaylight.openflowplugin.impl.services;
-import java.util.Collection;
-import java.util.concurrent.Future;
-
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import java.util.concurrent.Future;
+import javax.annotation.Nullable;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.Nullable;
-
public class SalMeterServiceImpl implements SalMeterService, ItemLifeCycleSource {
private static final Logger LOG = LoggerFactory.getLogger(SalMeterServiceImpl.class);
private final MeterService<AddMeterInput, AddMeterOutput> addMeter;
@Override
public Future<RpcResult<AddMeterOutput>> addMeter(final AddMeterInput input) {
- addMeter.getDeviceContext().getDeviceMeterRegistry().store(input.getMeterId());
+ addMeter.getDeviceRegistry().getDeviceMeterRegistry().store(input.getMeterId());
final ListenableFuture<RpcResult<AddMeterOutput>> resultFuture = addMeter.handleServiceCall(input);
Futures.addCallback(resultFuture, new FutureCallback<RpcResult<AddMeterOutput>>() {
@Override
public Future<RpcResult<RemoveMeterOutput>> removeMeter(final RemoveMeterInput input) {
- removeMeter.getDeviceContext().getDeviceMeterRegistry().markToBeremoved(input.getMeterId());
+ removeMeter.getDeviceRegistry().getDeviceMeterRegistry().markToBeremoved(input.getMeterId());
final ListenableFuture<RpcResult<RemoveMeterOutput>> resultFuture = removeMeter.handleServiceCall(input);
Futures.addCallback(resultFuture, new FutureCallback<RpcResult<RemoveMeterOutput>>() {
if (itemLifecycleListener != null) {
KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter, MeterKey> meterPath
= createMeterPath(meterId,
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
itemLifecycleListener.onRemoved(meterPath);
}
}
if (itemLifecycleListener != null) {
KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter, MeterKey> groupPath
= createMeterPath(meterId,
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
itemLifecycleListener.onAdded(groupPath, new MeterBuilder(data).build());
}
}
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.device.Xid;
import org.opendaylight.openflowplugin.impl.role.RoleChangeException;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
}
private ListenableFuture<RpcResult<SetRoleOutput>> tryToChangeRole(final OfpRole role) {
- LOG.info("RoleChangeTask called on device:{} OFPRole:{}", getNodeId().getValue(), role);
+ LOG.info("RoleChangeTask called on device:{} OFPRole:{}", getDeviceInfo().getNodeId().getValue(), role);
final Future<BigInteger> generationFuture = roleService.getGenerationIdFromDevice(getVersion());
return Futures.transform(JdkFutureAdapters.listenInPoolThread(generationFuture), (AsyncFunction<BigInteger, RpcResult<SetRoleOutput>>) generationId -> {
- LOG.debug("RoleChangeTask, GenerationIdFromDevice from device {} is {}", getNodeId().getValue(), generationId);
+ LOG.debug("RoleChangeTask, GenerationIdFromDevice from device {} is {}", getDeviceInfo().getNodeId().getValue(), generationId);
final BigInteger nextGenerationId = getNextGenerationId(generationId);
- LOG.debug("nextGenerationId received from device:{} is {}", getNodeId().getValue(), nextGenerationId);
+ LOG.debug("nextGenerationId received from device:{} is {}", getDeviceInfo().getNodeId().getValue(), nextGenerationId);
final Future<RpcResult<SetRoleOutput>> submitRoleFuture = roleService.submitRoleChange(role, getVersion(), nextGenerationId);
return JdkFutureAdapters.listenInPoolThread(submitRoleFuture);
});
final List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures> salTableFeatures = convertToSalTableFeatures(multipartReplies);
final InstanceIdentifier<FlowCapableNode> flowCapableNodeII = InstanceIdentifier.create(Nodes.class)
- .child(Node.class, new NodeKey(getNodeId())).augmentation(FlowCapableNode.class);
+ .child(Node.class, new NodeKey(getDeviceInfo().getNodeId())).augmentation(FlowCapableNode.class);
for (final org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures tableFeatureData : salTableFeatures) {
final Short tableId = tableFeatureData.getTableId();
final KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures, TableFeaturesKey> tableFeaturesII = flowCapableNodeII
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.FlowStatsResponseConvertor;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.GroupStatsResponseConvertor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.BytesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.PacketsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
package org.opendaylight.openflowplugin.impl.statistics;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Optional;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.impl.services.RequestContextUtil;
import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringOnTheFlyService;
import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class StatisticsContextImpl implements StatisticsContext {
+class StatisticsContextImpl implements StatisticsContext {
private static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImpl.class);
private static final String CONNECTION_CLOSED = "Connection closed.";
private StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService;
private Timeout pollTimeout;
- private final LifecycleConductor conductor;
private volatile boolean schedulingEnabled;
+ private volatile CONTEXT_STATE contextState;
- public StatisticsContextImpl(@CheckForNull final NodeId nodeId, final boolean shuttingDownStatisticsPolling, final LifecycleConductor lifecycleConductor) {
- this.conductor = lifecycleConductor;
- this.deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
+ StatisticsContextImpl(@CheckForNull final DeviceInfo deviceInfo, final boolean shuttingDownStatisticsPolling, final LifecycleConductor lifecycleConductor) {
+ this.deviceContext = Preconditions.checkNotNull(lifecycleConductor.getDeviceContext(deviceInfo));
this.devState = Preconditions.checkNotNull(deviceContext.getDeviceState());
this.shuttingDownStatisticsPolling = shuttingDownStatisticsPolling;
emptyFuture = Futures.immediateFuture(false);
statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService(this, deviceContext);
itemLifeCycleListener = new ItemLifecycleListenerImpl(deviceContext);
statListForCollectingInitialization();
- this.deviceContext.setStatisticsContext(StatisticsContextImpl.this);
+ contextState = CONTEXT_STATE.WORKING;
}
@Override
}
}
+
+ @Override
+ public ListenableFuture<Boolean> initialGatherDynamicData() {
+ return gatherDynamicData(true);
+ }
+
@Override
- public ListenableFuture<Boolean> gatherDynamicData() {
+ public ListenableFuture<Boolean> gatherDynamicData(){
+ return gatherDynamicData(false);
+ }
+
+ private ListenableFuture<Boolean> gatherDynamicData(final boolean initial) {
if (shuttingDownStatisticsPolling) {
- LOG.debug("Statistics for device {} is not enabled.", deviceContext.getDeviceState().getNodeId());
+ LOG.debug("Statistics for device {} is not enabled.", deviceContext.getDeviceInfo().getNodeId());
return Futures.immediateFuture(Boolean.TRUE);
}
final ListenableFuture<Boolean> errorResultFuture = deviceConnectionCheck();
// write start timestamp to state snapshot container
StatisticsGatheringUtils.markDeviceStateSnapshotStart(deviceContext);
- statChainFuture(statIterator, settableStatResultFuture);
+ statChainFuture(statIterator, settableStatResultFuture, initial);
// write end timestamp to state snapshot container
Futures.addCallback(settableStatResultFuture, new FutureCallback<Boolean>() {
}
}
- private ListenableFuture<Boolean> chooseStat(final MultipartType multipartType){
+ private ListenableFuture<Boolean> chooseStat(final MultipartType multipartType, final boolean initial){
switch (multipartType) {
case OFPMPFLOW:
- return collectFlowStatistics(multipartType);
+ return collectFlowStatistics(multipartType, initial);
case OFPMPTABLE:
return collectTableStatistics(multipartType);
case OFPMPPORTSTATS:
@Override
public void close() {
- schedulingEnabled = false;
- for (final Iterator<RequestContext<?>> iterator = Iterators.consumingIterator(requestContexts.iterator());
- iterator.hasNext();) {
- RequestContextUtil.closeRequestContextWithRpcError(iterator.next(), CONNECTION_CLOSED);
- }
- if (null != pollTimeout && !pollTimeout.isExpired()) {
- pollTimeout.cancel();
+ if (CONTEXT_STATE.TERMINATION.equals(contextState)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Statistics context is already in state TERMINATION.");
+ }
+ } else {
+ contextState = CONTEXT_STATE.TERMINATION;
+ schedulingEnabled = false;
+ for (final Iterator<RequestContext<?>> iterator = Iterators.consumingIterator(requestContexts.iterator());
+ iterator.hasNext(); ) {
+ RequestContextUtil.closeRequestContextWithRpcError(iterator.next(), CONNECTION_CLOSED);
+ }
+ if (null != pollTimeout && !pollTimeout.isExpired()) {
+ pollTimeout.cancel();
+ }
}
}
@Override
public Optional<Timeout> getPollTimeout() {
- return Optional.fromNullable(pollTimeout);
+ return Optional.ofNullable(pollTimeout);
}
- private void statChainFuture(final Iterator<MultipartType> iterator, final SettableFuture<Boolean> resultFuture) {
+ private void statChainFuture(final Iterator<MultipartType> iterator, final SettableFuture<Boolean> resultFuture, final boolean initial) {
if (ConnectionContext.CONNECTION_STATE.RIP.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
final String errMsg = String.format("Device connection is closed for Node : %s.",
- deviceContext.getDeviceState().getNodeId());
+ deviceContext.getDeviceInfo().getNodeId());
LOG.debug(errMsg);
resultFuture.setException(new IllegalStateException(errMsg));
return;
}
if ( ! iterator.hasNext()) {
resultFuture.set(Boolean.TRUE);
- LOG.debug("Stats collection successfully finished for node {}", deviceContext.getDeviceState().getNodeId());
+ LOG.debug("Stats collection successfully finished for node {}", deviceContext.getDeviceInfo().getNodeId());
return;
}
final MultipartType nextType = iterator.next();
- LOG.debug("Stats iterating to next type for node {} of type {}", deviceContext.getDeviceState().getNodeId(), nextType);
+ LOG.debug("Stats iterating to next type for node {} of type {}", deviceContext.getDeviceInfo().getNodeId(), nextType);
- final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = chooseStat(nextType);
+ final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = chooseStat(nextType, initial);
Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback<Boolean>() {
@Override
public void onSuccess(final Boolean result) {
- statChainFuture(iterator, resultFuture);
+ statChainFuture(iterator, resultFuture, initial);
}
@Override
public void onFailure(@Nonnull final Throwable t) {
@VisibleForTesting
ListenableFuture<Boolean> deviceConnectionCheck() {
if (!ConnectionContext.CONNECTION_STATE.WORKING.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
- ListenableFuture<Boolean> resultingFuture = SettableFuture.create();
+ ListenableFuture<Boolean> resultingFuture;
switch (deviceContext.getPrimaryConnectionContext().getConnectionState()) {
case RIP:
final String errMsg = String.format("Device connection doesn't exist anymore. Primary connection status : %s",
return null;
}
- private ListenableFuture<Boolean> collectFlowStatistics(final MultipartType multipartType) {
+ //TODO: Refactor twice sending deviceContext into gatheringStatistics
+ private ListenableFuture<Boolean> collectFlowStatistics(final MultipartType multipartType, final boolean initial) {
return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringOnTheFlyService, deviceContext, /*MultipartType.OFPMPFLOW*/ multipartType) : emptyFuture;
+ statisticsGatheringOnTheFlyService,
+ deviceContext.getDeviceInfo(),
+ /*MultipartType.OFPMPFLOW*/ multipartType,
+ deviceContext,
+ deviceContext,
+ initial) : emptyFuture;
}
private ListenableFuture<Boolean> collectTableStatistics(final MultipartType multipartType) {
return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPTABLE*/ multipartType) : emptyFuture;
+ statisticsGatheringService,
+ deviceContext.getDeviceInfo(),
+ /*MultipartType.OFPMPTABLE*/ multipartType,
+ deviceContext,
+ deviceContext,
+ false) : emptyFuture;
}
private ListenableFuture<Boolean> collectPortStatistics(final MultipartType multipartType) {
return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPPORTSTATS*/ multipartType) : emptyFuture;
+ statisticsGatheringService,
+ deviceContext.getDeviceInfo(),
+ /*MultipartType.OFPMPPORTSTATS*/ multipartType,
+ deviceContext,
+ deviceContext,
+ false) : emptyFuture;
}
private ListenableFuture<Boolean> collectQueueStatistics(final MultipartType multipartType) {
- return devState.isQueueStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPQUEUE*/ multipartType) : emptyFuture;
+ return !devState.isQueueStatisticsAvailable() ? emptyFuture : StatisticsGatheringUtils.gatherStatistics(
+ statisticsGatheringService,
+ deviceContext.getDeviceInfo(),
+ /*MultipartType.OFPMPQUEUE*/ multipartType,
+ deviceContext,
+ deviceContext,
+ false);
}
private ListenableFuture<Boolean> collectGroupDescStatistics(final MultipartType multipartType) {
return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUPDESC*/ multipartType) : emptyFuture;
+ statisticsGatheringService,
+ deviceContext.getDeviceInfo(),
+ /*MultipartType.OFPMPGROUPDESC*/ multipartType,
+ deviceContext,
+ deviceContext,
+ false) : emptyFuture;
}
private ListenableFuture<Boolean> collectGroupStatistics(final MultipartType multipartType) {
return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUP*/ multipartType) : emptyFuture;
+ statisticsGatheringService,
+ deviceContext.getDeviceInfo(),
+ /*MultipartType.OFPMPGROUP*/ multipartType,
+ deviceContext,
+ deviceContext,
+ false) : emptyFuture;
}
private ListenableFuture<Boolean> collectMeterConfigStatistics(final MultipartType multipartType) {
return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETERCONFIG*/ multipartType) : emptyFuture;
+ statisticsGatheringService,
+ deviceContext.getDeviceInfo(),
+ /*MultipartType.OFPMPMETERCONFIG*/ multipartType,
+ deviceContext,
+ deviceContext,
+ false) : emptyFuture;
}
private ListenableFuture<Boolean> collectMeterStatistics(final MultipartType multipartType) {
return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETER*/ multipartType) : emptyFuture;
+ statisticsGatheringService,
+ deviceContext.getDeviceInfo(),
+ /*MultipartType.OFPMPMETER*/ multipartType,
+ deviceContext,
+ deviceContext,
+ false) : emptyFuture;
}
@VisibleForTesting
return itemLifeCycleListener;
}
-
@Override
- public DeviceContext getDeviceContext() {
- return deviceContext;
+ public CONTEXT_STATE getState() {
+ return contextState;
}
}
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceRegistry;
import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
+import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
+import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.StatisticsGatherer;
import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
import org.slf4j.LoggerFactory;
/**
- * Created by Martin Bobak <mbobak@cisco.com> on 2.4.2015.
+ * Utils for gatherig statistics
*/
public final class StatisticsGatheringUtils {
- public static String DATE_AND_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
+ private static String DATE_AND_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
private static final Logger LOG = LoggerFactory.getLogger(StatisticsGatheringUtils.class);
private static final SinglePurposeMultipartReplyTranslator MULTIPART_REPLY_TRANSLATOR = new SinglePurposeMultipartReplyTranslator();
- public static final String QUEUE2_REQCTX = "QUEUE2REQCTX-";
+ private static final String QUEUE2_REQCTX = "QUEUE2REQCTX-";
private StatisticsGatheringUtils() {
throw new IllegalStateException("This class should not be instantiated.");
}
-
- public static ListenableFuture<Boolean> gatherStatistics(final StatisticsGatherer statisticsGatheringService,
- final DeviceContext deviceContext,
- final MultipartType type) {
- final String deviceId = deviceContext.getPrimaryConnectionContext().getNodeId().toString();
+ //TODO: Flow-,Group- and Meter- registry should be not in device context, consider move it in separate class
+ static ListenableFuture<Boolean> gatherStatistics(final StatisticsGatherer statisticsGatheringService,
+ final DeviceInfo deviceInfo,
+ final MultipartType type,
+ final TxFacade txFacade,
+ final DeviceRegistry registry,
+ final Boolean initial) {
EventIdentifier wholeProcessEventIdentifier = null;
if (MultipartType.OFPMPFLOW.equals(type)) {
- wholeProcessEventIdentifier = new EventIdentifier(type.toString(), deviceId);
+ wholeProcessEventIdentifier = new EventIdentifier(type.toString(), deviceInfo.getNodeId().getValue());
EventsTimeCounter.markStart(wholeProcessEventIdentifier);
}
- final EventIdentifier ofpQueuToRequestContextEventIdentifier = new EventIdentifier(QUEUE2_REQCTX + type.toString(), deviceId);
+ final EventIdentifier ofpQueuToRequestContextEventIdentifier = new EventIdentifier(QUEUE2_REQCTX + type.toString(), deviceInfo.getNodeId().toString());
final ListenableFuture<RpcResult<List<MultipartReply>>> statisticsDataInFuture =
JdkFutureAdapters.listenInPoolThread(statisticsGatheringService.getStatisticsOfType(
ofpQueuToRequestContextEventIdentifier, type));
- return transformAndStoreStatisticsData(statisticsDataInFuture, deviceContext, wholeProcessEventIdentifier, type);
+ return transformAndStoreStatisticsData(statisticsDataInFuture, deviceInfo, wholeProcessEventIdentifier, type, txFacade, registry, initial);
}
private static ListenableFuture<Boolean> transformAndStoreStatisticsData(final ListenableFuture<RpcResult<List<MultipartReply>>> statisticsDataInFuture,
- final DeviceContext deviceContext,
- final EventIdentifier eventIdentifier, final MultipartType type) {
+ final DeviceInfo deviceInfo,
+ final EventIdentifier eventIdentifier,
+ final MultipartType type,
+ final TxFacade txFacade,
+ final DeviceRegistry registry,
+ final boolean initial) {
return Futures.transform(statisticsDataInFuture, new AsyncFunction<RpcResult<List<MultipartReply>>, Boolean>() {
@Nullable
@Override
public ListenableFuture<Boolean> apply(final RpcResult<List<MultipartReply>> rpcResult) {
boolean isMultipartProcessed = Boolean.TRUE;
if (rpcResult.isSuccessful()) {
- LOG.debug("Stats reply successfully received for node {} of type {}", deviceContext.getDeviceState().getNodeId(), type);
+ LOG.debug("Stats reply successfully received for node {} of type {}", deviceInfo.getNodeId(), type);
// TODO: in case the result value is null then multipart data probably got processed on the fly -
// TODO: this contract should by clearly stated and enforced - now simple true value is returned
try {
for (final MultipartReply singleReply : rpcResult.getResult()) {
final List<? extends DataObject> multipartDataList = MULTIPART_REPLY_TRANSLATOR.translate(
- deviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId(),
- deviceContext.getPrimaryConnectionContext().getFeatures().getVersion(), singleReply);
+ deviceInfo.getDatapathId(),
+ deviceInfo.getVersion(), singleReply);
multipartData = multipartDataList.get(0);
allMultipartData = Iterables.concat(allMultipartData, multipartDataList);
}
} catch (final Exception e) {
LOG.warn("stats processing of type {} for node {} failed during transfomation step",
- type, deviceContext.getDeviceState().getNodeId(), e);
+ type, deviceInfo.getNodeId(), e);
return Futures.immediateFailedFuture(e);
}
try {
if (multipartData instanceof GroupStatisticsUpdated) {
- processGroupStatistics((Iterable<GroupStatisticsUpdated>) allMultipartData, deviceContext);
+ processGroupStatistics((Iterable<GroupStatisticsUpdated>) allMultipartData, deviceInfo, txFacade);
} else if (multipartData instanceof MeterStatisticsUpdated) {
- processMetersStatistics((Iterable<MeterStatisticsUpdated>) allMultipartData, deviceContext);
+ processMetersStatistics((Iterable<MeterStatisticsUpdated>) allMultipartData, deviceInfo, txFacade);
} else if (multipartData instanceof NodeConnectorStatisticsUpdate) {
- processNodeConnectorStatistics((Iterable<NodeConnectorStatisticsUpdate>) allMultipartData, deviceContext);
+ processNodeConnectorStatistics((Iterable<NodeConnectorStatisticsUpdate>) allMultipartData, deviceInfo, txFacade);
} else if (multipartData instanceof FlowTableStatisticsUpdate) {
- processFlowTableStatistics((Iterable<FlowTableStatisticsUpdate>) allMultipartData, deviceContext);
+ processFlowTableStatistics((Iterable<FlowTableStatisticsUpdate>) allMultipartData, deviceInfo, txFacade);
} else if (multipartData instanceof QueueStatisticsUpdate) {
- processQueueStatistics((Iterable<QueueStatisticsUpdate>) allMultipartData, deviceContext);
+ processQueueStatistics((Iterable<QueueStatisticsUpdate>) allMultipartData, deviceInfo, txFacade);
} else if (multipartData instanceof FlowsStatisticsUpdate) {
/* FlowStat Processing is realized by NettyThread only by initPhase, otherwise it is realized
* by MD-SAL thread */
- return processFlowStatistics((Iterable<FlowsStatisticsUpdate>) allMultipartData, deviceContext, eventIdentifier);
+ return processFlowStatistics((Iterable<FlowsStatisticsUpdate>) allMultipartData, deviceInfo, txFacade, registry.getDeviceFlowRegistry(), initial, eventIdentifier);
} else if (multipartData instanceof GroupDescStatsUpdated) {
- processGroupDescStats((Iterable<GroupDescStatsUpdated>) allMultipartData, deviceContext);
+ processGroupDescStats((Iterable<GroupDescStatsUpdated>) allMultipartData, deviceInfo, txFacade, registry.getDeviceGroupRegistry());
} else if (multipartData instanceof MeterConfigStatsUpdated) {
- processMeterConfigStatsUpdated((Iterable<MeterConfigStatsUpdated>) allMultipartData, deviceContext);
+ processMeterConfigStatsUpdated((Iterable<MeterConfigStatsUpdated>) allMultipartData, deviceInfo, txFacade, registry.getDeviceMeterRegistry());
} else {
isMultipartProcessed = Boolean.FALSE;
}
} catch (final Exception e) {
LOG.warn("stats processing of type {} for node {} failed during write-to-tx step",
- type, deviceContext.getDeviceState().getNodeId(), e);
+ type, deviceInfo.getNodeId(), e);
return Futures.immediateFailedFuture(e);
}
- LOG.debug("Stats reply added to transaction for node {} of type {}", deviceContext.getDeviceState().getNodeId(), type);
+ LOG.debug("Stats reply added to transaction for node {} of type {}", deviceInfo.getNodeId(), type);
//TODO : implement experimenter
} else {
- LOG.debug("Stats reply was empty for node {} of type {}", deviceContext.getDeviceState().getNodeId(), type);
+ LOG.debug("Stats reply was empty for node {} of type {}", deviceInfo.getNodeId(), type);
}
} else {
- LOG.debug("Stats reply FAILED for node {} of type {}: {}", deviceContext.getDeviceState().getNodeId(), type, rpcResult.getErrors());
+ LOG.debug("Stats reply FAILED for node {} of type {}: {}", deviceInfo.getNodeId(), type, rpcResult.getErrors());
isMultipartProcessed = Boolean.FALSE;
}
return Futures.immediateFuture(isMultipartProcessed);
});
}
- private static void processMeterConfigStatsUpdated(final Iterable<MeterConfigStatsUpdated> data, final DeviceContext deviceContext) throws Exception {
- final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext.getDeviceState());
- deleteAllKnownMeters(deviceContext, fNodeIdent);
+ private static void processMeterConfigStatsUpdated(final Iterable<MeterConfigStatsUpdated> data,
+ final DeviceInfo deviceInfo,
+ final TxFacade txFacade,
+ final DeviceMeterRegistry meterRegistry) throws Exception {
+ final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
+ deleteAllKnownMeters(meterRegistry, fNodeIdent, txFacade);
for (final MeterConfigStatsUpdated meterConfigStatsUpdated : data) {
for (final MeterConfigStats meterConfigStats : meterConfigStatsUpdated.getMeterConfigStats()) {
final MeterId meterId = meterConfigStats.getMeterId();
final MeterBuilder meterBuilder = new MeterBuilder(meterConfigStats);
meterBuilder.setKey(new MeterKey(meterId));
meterBuilder.addAugmentation(NodeMeterStatistics.class, new NodeMeterStatisticsBuilder().build());
- deviceContext.getDeviceMeterRegistry().store(meterId);
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, meterInstanceIdentifier, meterBuilder.build());
+ meterRegistry.store(meterId);
+ txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, meterInstanceIdentifier, meterBuilder.build());
}
}
- deviceContext.submitTransaction();
+ txFacade.submitTransaction();
}
private static ListenableFuture<Boolean> processFlowStatistics(final Iterable<FlowsStatisticsUpdate> data,
- final DeviceContext deviceContext, final EventIdentifier eventIdentifier) {
- final ListenableFuture<Void> deleFuture = deleteAllKnownFlows(deviceContext.getDeviceState(),
- deviceContext.getDeviceFlowRegistry(), deviceContext);
- return Futures.transform(deleFuture, new Function<Void, Boolean>() {
+ final DeviceInfo deviceInfo,
+ final TxFacade txFacade,
+ final DeviceFlowRegistry flowRegistry,
+ final boolean initial,
+ final EventIdentifier eventIdentifier) {
+ final ListenableFuture<Void> deleteFuture = initial ? Futures.immediateFuture(null) : deleteAllKnownFlows(deviceInfo,
+ flowRegistry, txFacade);
+ return Futures.transform(deleteFuture, new Function<Void, Boolean>() {
@Override
public Boolean apply(final Void input) {
- writeFlowStatistics(data, deviceContext.getDeviceState(), deviceContext.getDeviceFlowRegistry(),
- deviceContext);
- deviceContext.submitTransaction();
+ writeFlowStatistics(data, deviceInfo, flowRegistry, txFacade);
+ txFacade.submitTransaction();
EventsTimeCounter.markEnd(eventIdentifier);
return Boolean.TRUE;
}
}
public static void writeFlowStatistics(final Iterable<FlowsStatisticsUpdate> data,
- final DeviceState deviceState,
+ final DeviceInfo deviceInfo,
final DeviceFlowRegistry registry,
final TxFacade txFacade) {
- final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceState);
+ final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
try {
for (final FlowsStatisticsUpdate flowsStatistics : data) {
for (final FlowAndStatisticsMapList flowStat : flowsStatistics.getFlowAndStatisticsMapList()) {
return flowStatisticsDataBld;
}
- public static ListenableFuture<Void> deleteAllKnownFlows(final DeviceState deviceState,
+ public static ListenableFuture<Void> deleteAllKnownFlows(final DeviceInfo deviceInfo,
final DeviceFlowRegistry registry,
final TxFacade txFacade) {
- /* DeviceState.deviceSynchronized is a marker for actual phase - false means initPhase, true means noInitPhase */
- if (deviceState.deviceSynchronized()) {
- final InstanceIdentifier<FlowCapableNode> flowCapableNodePath = assembleFlowCapableNodeInstanceIdentifier(deviceState);
- final ReadOnlyTransaction readTx = txFacade.getReadTransaction();
- final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> flowCapableNodeFuture = readTx.read(
- LogicalDatastoreType.OPERATIONAL, flowCapableNodePath);
-
- /* we wish to close readTx for fallBack */
- Futures.withFallback(flowCapableNodeFuture, new FutureFallback<Optional<FlowCapableNode>>() {
-
- @Override
- public ListenableFuture<Optional<FlowCapableNode>> create(final Throwable t) throws Exception {
- readTx.close();
- return Futures.immediateFailedFuture(t);
- }
- });
- /*
- * we have to read actual tables with all information before we set empty Flow list, merge is expensive and
- * not applicable for lists
- */
- return Futures.transform(flowCapableNodeFuture, new AsyncFunction<Optional<FlowCapableNode>, Void>() {
-
- @Override
- public ListenableFuture<Void> apply(final Optional<FlowCapableNode> flowCapNodeOpt) throws Exception {
- if (flowCapNodeOpt.isPresent()) {
- for (final Table tableData : flowCapNodeOpt.get().getTable()) {
- final Table table = new TableBuilder(tableData).setFlow(Collections.<Flow>emptyList()).build();
- final InstanceIdentifier<Table> iiToTable = flowCapableNodePath.child(Table.class, tableData.getKey());
- txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, iiToTable, table);
- }
+ final InstanceIdentifier<FlowCapableNode> flowCapableNodePath = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
+ final ReadOnlyTransaction readTx = txFacade.getReadTransaction();
+ final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> flowCapableNodeFuture = readTx.read(
+ LogicalDatastoreType.OPERATIONAL, flowCapableNodePath);
+
+ /* we wish to close readTx for fallBack */
+ Futures.withFallback(flowCapableNodeFuture, new FutureFallback<Optional<FlowCapableNode>>() {
+
+ @Override
+ public ListenableFuture<Optional<FlowCapableNode>> create(final Throwable t) throws Exception {
+ readTx.close();
+ return Futures.immediateFailedFuture(t);
+ }
+ });
+ /*
+ * we have to read actual tables with all information before we set empty Flow list, merge is expensive and
+ * not applicable for lists
+ */
+ return Futures.transform(flowCapableNodeFuture, new AsyncFunction<Optional<FlowCapableNode>, Void>() {
+
+ @Override
+ public ListenableFuture<Void> apply(final Optional<FlowCapableNode> flowCapNodeOpt) throws Exception {
+ if (flowCapNodeOpt.isPresent()) {
+ for (final Table tableData : flowCapNodeOpt.get().getTable()) {
+ final Table table = new TableBuilder(tableData).setFlow(Collections.<Flow>emptyList()).build();
+ final InstanceIdentifier<Table> iiToTable = flowCapableNodePath.child(Table.class, tableData.getKey());
+ txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, iiToTable, table);
}
- registry.removeMarked();
- readTx.close();
- return Futures.immediateFuture(null);
}
+ registry.removeMarked();
+ readTx.close();
+ return Futures.immediateFuture(null);
+ }
- });
- }
- return Futures.immediateFuture(null);
+ });
}
- private static void processQueueStatistics(final Iterable<QueueStatisticsUpdate> data, final DeviceContext deviceContext) throws Exception {
+ private static void processQueueStatistics(final Iterable<QueueStatisticsUpdate> data, final DeviceInfo deviceInfo, final TxFacade txFacade) throws Exception {
// TODO: clean all queues of all node-connectors before writing up-to-date stats
- final InstanceIdentifier<Node> nodeIdent = deviceContext.getDeviceState().getNodeInstanceIdentifier();
+ final InstanceIdentifier<Node> nodeIdent = deviceInfo.getNodeInstanceIdentifier();
for (final QueueStatisticsUpdate queueStatisticsUpdate : data) {
for (final QueueIdAndStatisticsMap queueStat : queueStatisticsUpdate.getQueueIdAndStatisticsMap()) {
if (queueStat.getQueueId() != null) {
.setQueueId(queueStat.getQueueId())
// node-connector-id is already contained in parent node and the port-id here is of incompatible format
.addAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class, statBuild.build());
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, queueIdent, queueBuilder.build());
+ txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, queueIdent, queueBuilder.build());
}
}
}
- deviceContext.submitTransaction();
+ txFacade.submitTransaction();
}
- private static void processFlowTableStatistics(final Iterable<FlowTableStatisticsUpdate> data, final DeviceContext deviceContext) throws Exception {
- final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext.getDeviceState());
+ private static void processFlowTableStatistics(final Iterable<FlowTableStatisticsUpdate> data, final DeviceInfo deviceInfo, final TxFacade txFacade) throws Exception {
+ final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
for (final FlowTableStatisticsUpdate flowTableStatisticsUpdate : data) {
for (final FlowTableAndStatisticsMap tableStat : flowTableStatisticsUpdate.getFlowTableAndStatisticsMap()) {
final InstanceIdentifier<FlowTableStatistics> tStatIdent = fNodeIdent.child(Table.class, new TableKey(tableStat.getTableId().getValue()))
.augmentation(FlowTableStatisticsData.class).child(FlowTableStatistics.class);
final FlowTableStatistics stats = new FlowTableStatisticsBuilder(tableStat).build();
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tStatIdent, stats);
+ txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tStatIdent, stats);
}
}
- deviceContext.submitTransaction();
+ txFacade.submitTransaction();
}
- private static void processNodeConnectorStatistics(final Iterable<NodeConnectorStatisticsUpdate> data, final DeviceContext deviceContext) throws Exception {
- final InstanceIdentifier<Node> nodeIdent = deviceContext.getDeviceState().getNodeInstanceIdentifier();
+ private static void processNodeConnectorStatistics(final Iterable<NodeConnectorStatisticsUpdate> data, final DeviceInfo deviceInfo, final TxFacade txFacade) throws Exception {
+ final InstanceIdentifier<Node> nodeIdent = deviceInfo.getNodeInstanceIdentifier();
for (final NodeConnectorStatisticsUpdate nodeConnectorStatisticsUpdate : data) {
for (final NodeConnectorStatisticsAndPortNumberMap nConnectPort : nodeConnectorStatisticsUpdate.getNodeConnectorStatisticsAndPortNumberMap()) {
final FlowCapableNodeConnectorStatistics stats = new FlowCapableNodeConnectorStatisticsBuilder(nConnectPort).build();
.augmentation(FlowCapableNodeConnectorStatisticsData.class);
final InstanceIdentifier<FlowCapableNodeConnectorStatistics> flowCapNodeConnStatIdent =
nodeConnStatIdent.child(FlowCapableNodeConnectorStatistics.class);
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowCapNodeConnStatIdent, stats);
+ txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowCapNodeConnStatIdent, stats);
}
}
- deviceContext.submitTransaction();
+ txFacade.submitTransaction();
}
private static void processMetersStatistics(final Iterable<MeterStatisticsUpdated> data,
- final DeviceContext deviceContext) throws Exception {
- final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext.getDeviceState());
+ final DeviceInfo deviceInfo,
+ final TxFacade txFacade) throws Exception {
+ final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
for (final MeterStatisticsUpdated meterStatisticsUpdated : data) {
for (final MeterStats mStat : meterStatisticsUpdated.getMeterStats()) {
final MeterStatistics stats = new MeterStatisticsBuilder(mStat).build();
final InstanceIdentifier<NodeMeterStatistics> nodeMeterStatIdent = meterIdent
.augmentation(NodeMeterStatistics.class);
final InstanceIdentifier<MeterStatistics> msIdent = nodeMeterStatIdent.child(MeterStatistics.class);
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, msIdent, stats);
+ txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, msIdent, stats);
}
}
- deviceContext.submitTransaction();
+ txFacade.submitTransaction();
}
- private static void deleteAllKnownMeters(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) throws Exception {
- for (final MeterId meterId : deviceContext.getDeviceMeterRegistry().getAllMeterIds()) {
+ private static void deleteAllKnownMeters(final DeviceMeterRegistry meterRegistry, final InstanceIdentifier<FlowCapableNode> fNodeIdent, final TxFacade txFacade) throws Exception {
+ for (final MeterId meterId : meterRegistry.getAllMeterIds()) {
final InstanceIdentifier<Meter> meterIdent = fNodeIdent.child(Meter.class, new MeterKey(meterId));
- deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, meterIdent);
+ txFacade.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, meterIdent);
}
- deviceContext.getDeviceMeterRegistry().removeMarked();
+ meterRegistry.removeMarked();
}
- private static void processGroupDescStats(final Iterable<GroupDescStatsUpdated> data, final DeviceContext deviceContext) throws Exception {
- final InstanceIdentifier<FlowCapableNode> fNodeIdent =
- deviceContext.getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
- deleteAllKnownGroups(deviceContext, fNodeIdent);
+ private static void processGroupDescStats(final Iterable<GroupDescStatsUpdated> data, final DeviceInfo deviceInfo, final TxFacade txFacade, final DeviceGroupRegistry groupRegistry) throws Exception {
+ final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
+ deleteAllKnownGroups(txFacade, fNodeIdent, groupRegistry);
for (final GroupDescStatsUpdated groupDescStatsUpdated : data) {
for (final GroupDescStats groupDescStats : groupDescStatsUpdated.getGroupDescStats()) {
final InstanceIdentifier<Group> groupIdent = fNodeIdent.child(Group.class, new GroupKey(groupId));
- deviceContext.getDeviceGroupRegistry().store(groupId);
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, groupIdent, groupBuilder.build());
+ groupRegistry.store(groupId);
+ txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, groupIdent, groupBuilder.build());
}
}
- deviceContext.submitTransaction();
+ txFacade.submitTransaction();
}
- private static void deleteAllKnownGroups(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) throws Exception {
- for (final GroupId groupId : deviceContext.getDeviceGroupRegistry().getAllGroupIds()) {
+ private static void deleteAllKnownGroups(final TxFacade txFacade, final InstanceIdentifier<FlowCapableNode> fNodeIdent, final DeviceGroupRegistry groupRegistry) throws Exception {
+ for (final GroupId groupId : groupRegistry.getAllGroupIds()) {
final InstanceIdentifier<Group> groupIdent = fNodeIdent.child(Group.class, new GroupKey(groupId));
- deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, groupIdent);
+ txFacade.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, groupIdent);
}
- deviceContext.getDeviceGroupRegistry().removeMarked();
+ groupRegistry.removeMarked();
}
- private static void processGroupStatistics(final Iterable<GroupStatisticsUpdated> data, final DeviceContext deviceContext) throws Exception {
- final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext.getDeviceState());
+ private static void processGroupStatistics(final Iterable<GroupStatisticsUpdated> data, final DeviceInfo deviceInfo, final TxFacade txFacade) throws Exception {
+ final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceInfo);
for (final GroupStatisticsUpdated groupStatistics : data) {
for (final GroupStats groupStats : groupStatistics.getGroupStats()) {
final InstanceIdentifier<GroupStatistics> gsIdent = nGroupStatIdent.child(GroupStatistics.class);
final GroupStatistics stats = new GroupStatisticsBuilder(groupStats).build();
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, gsIdent, stats);
+ txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, gsIdent, stats);
}
}
- deviceContext.submitTransaction();
+ txFacade.submitTransaction();
}
- private static InstanceIdentifier<FlowCapableNode> assembleFlowCapableNodeInstanceIdentifier(final DeviceState deviceState) {
- return deviceState.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+ private static InstanceIdentifier<FlowCapableNode> assembleFlowCapableNodeInstanceIdentifier(final DeviceInfo deviceInfo) {
+ return deviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
}
/**
* @param deviceContext txManager + node path keeper
*/
static void markDeviceStateSnapshotStart(final DeviceContext deviceContext) {
- final InstanceIdentifier<FlowCapableStatisticsGatheringStatus> statusPath = deviceContext.getDeviceState()
+ final InstanceIdentifier<FlowCapableStatisticsGatheringStatus> statusPath = deviceContext.getDeviceInfo()
.getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class);
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_AND_TIME_FORMAT);
* @param succeeded outcome of currently finished gathering
*/
static void markDeviceStateSnapshotEnd(final DeviceContext deviceContext, final boolean succeeded) {
- final InstanceIdentifier<SnapshotGatheringStatusEnd> statusEndPath = deviceContext.getDeviceState()
+ final InstanceIdentifier<SnapshotGatheringStatusEnd> statusEndPath = deviceContext.getDeviceInfo()
.getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class)
.child(SnapshotGatheringStatusEnd.class);
package org.opendaylight.openflowplugin.impl.statistics;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.Iterators;
import com.google.common.util.concurrent.ListenableFuture;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.ChangeStatisticsWorkModeInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutputBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-import java.util.Iterator;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Future;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
public class StatisticsManagerImpl implements StatisticsManager, StatisticsManagerControlService {
private static final Logger LOG = LoggerFactory.getLogger(StatisticsManagerImpl.class);
private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
- private final ConcurrentMap<NodeId, StatisticsContext> contexts = new ConcurrentHashMap<>();
+ private final ConcurrentMap<DeviceInfo, StatisticsContext> contexts = new ConcurrentHashMap<>();
private static final long basicTimerDelay = 3000;
private static long currentTimerDelay = basicTimerDelay;
}
@Override
- public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
+ public void onDeviceContextLevelUp(final DeviceInfo deviceInfo) throws Exception {
- final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
+ final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(deviceInfo));
- final StatisticsContext statisticsContext = new StatisticsContextImpl(nodeId, shuttingDownStatisticsPolling, conductor);
- Verify.verify(contexts.putIfAbsent(nodeId, statisticsContext) == null, "StatisticsCtx still not closed for Node {}", nodeId);
+ final StatisticsContext statisticsContext = new StatisticsContextImpl(deviceInfo, shuttingDownStatisticsPolling, conductor);
+ Verify.verify(contexts.putIfAbsent(deviceInfo, statisticsContext) == null, "StatisticsCtx still not closed for Node {}", deviceInfo.getNodeId());
- deviceContext.getDeviceState().setDeviceSynchronized(true);
- deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
+ deviceInitPhaseHandler.onDeviceContextLevelUp(deviceInfo);
}
@VisibleForTesting
- void pollStatistics(final DeviceContext deviceContext,
- final StatisticsContext statisticsContext,
- final TimeCounter timeCounter) {
-
- final NodeId nodeId = deviceContext.getDeviceState().getNodeId();
+ void pollStatistics(final DeviceState deviceState,
+ final StatisticsContext statisticsContext,
+ final TimeCounter timeCounter,
+ final DeviceInfo deviceInfo) {
if (!statisticsContext.isSchedulingEnabled()) {
- LOG.debug("Disabling statistics scheduling for device: {}", nodeId);
+ LOG.debug("Disabling statistics scheduling for device: {}", deviceInfo.getNodeId());
return;
}
- if (!deviceContext.getDeviceState().isValid()) {
- LOG.debug("Session is not valid for device: {}", nodeId);
+ if (!deviceState.isValid()) {
+ LOG.debug("Session is not valid for device: {}", deviceInfo.getNodeId());
return;
}
- if (!deviceContext.getDeviceState().isStatisticsPollingEnabled()) {
- LOG.debug("Statistics polling is currently disabled for device: {}", nodeId);
- scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+ if (!deviceState.isStatisticsPollingEnabled()) {
+ LOG.debug("Statistics polling is currently disabled for device: {}", deviceInfo.getNodeId());
+ scheduleNextPolling(deviceState, deviceInfo, statisticsContext, timeCounter);
return;
}
- LOG.debug("POLLING ALL STATISTICS for device: {}", nodeId);
+ LOG.debug("POLLING ALL STATISTICS for device: {}", deviceInfo.getNodeId());
timeCounter.markStart();
final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = statisticsContext.gatherDynamicData();
Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback<Boolean>() {
public void onSuccess(final Boolean o) {
timeCounter.addTimeMark();
calculateTimerDelay(timeCounter);
- scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+ scheduleNextPolling(deviceState, deviceInfo, statisticsContext, timeCounter);
}
@Override
calculateTimerDelay(timeCounter);
if (throwable instanceof CancellationException) {
/** This often happens when something wrong with akka or DS, so closing connection will help to restart device **/
- conductor.closeConnection(deviceContext.getDeviceState().getNodeId());
+ conductor.closeConnection(deviceInfo);
} else {
- scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+ scheduleNextPolling(deviceState, deviceInfo, statisticsContext, timeCounter);
}
}
});
final long averageTime = TimeUnit.MILLISECONDS.toSeconds(timeCounter.getAverageTimeBetweenMarks());
final long STATS_TIMEOUT_SEC = averageTime > 0 ? 3 * averageTime : DEFAULT_STATS_TIMEOUT_SEC;
- final TimerTask timerTask = new TimerTask() {
-
- @Override
- public void run(final Timeout timeout) throws Exception {
- if (!deviceStatisticsCollectionFuture.isDone()) {
- LOG.info("Statistics collection for node {} still in progress even after {} secs", nodeId, STATS_TIMEOUT_SEC);
- deviceStatisticsCollectionFuture.cancel(true);
- }
+ final TimerTask timerTask = timeout -> {
+ if (!deviceStatisticsCollectionFuture.isDone()) {
+ LOG.info("Statistics collection for node {} still in progress even after {} secs", deviceInfo.getNodeId(), STATS_TIMEOUT_SEC);
+ deviceStatisticsCollectionFuture.cancel(true);
}
};
conductor.newTimeout(timerTask, STATS_TIMEOUT_SEC, TimeUnit.SECONDS);
}
- private void scheduleNextPolling(final DeviceContext deviceContext,
+ private void scheduleNextPolling(final DeviceState deviceState,
+ final DeviceInfo deviceInfo,
final StatisticsContext statisticsContext,
final TimeCounter timeCounter) {
- LOG.debug("SCHEDULING NEXT STATISTICS POLLING for device: {}", deviceContext.getDeviceState().getNodeId());
+ LOG.debug("SCHEDULING NEXT STATISTICS POLLING for device: {}", deviceInfo.getNodeId());
if (!shuttingDownStatisticsPolling) {
- final Timeout pollTimeout = conductor.newTimeout(new TimerTask() {
- @Override
- public void run(final Timeout timeout) throws Exception {
- pollStatistics(deviceContext, statisticsContext, timeCounter);
- }
- }, currentTimerDelay, TimeUnit.MILLISECONDS);
+ final Timeout pollTimeout = conductor.newTimeout(timeout -> pollStatistics(deviceState, statisticsContext, timeCounter, deviceInfo), currentTimerDelay, TimeUnit.MILLISECONDS);
statisticsContext.setPollTimeout(pollTimeout);
}
}
}
@Override
- public void onDeviceContextLevelDown(final DeviceContext deviceContext) {
- final StatisticsContext statisticsContext = contexts.remove(deviceContext.getDeviceState().getNodeId());
+ public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
+ final StatisticsContext statisticsContext = contexts.remove(deviceInfo);
if (null != statisticsContext) {
- LOG.trace("Removing device context from stack. No more statistics gathering for device: {}", deviceContext.getDeviceState().getNodeId());
+ LOG.trace("Removing device context from stack. No more statistics gathering for device: {}", deviceInfo.getNodeId());
statisticsContext.close();
}
- deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceContext);
+ deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
}
@Override
if (!workMode.equals(targetWorkMode)) {
shuttingDownStatisticsPolling = StatisticsWorkMode.FULLYDISABLED.equals(targetWorkMode);
// iterate through stats-ctx: propagate mode
- for (final StatisticsContext statisticsContext : contexts.values()) {
- final DeviceContext deviceContext = statisticsContext.getDeviceContext();
+ for (Map.Entry<DeviceInfo, StatisticsContext> entry : contexts.entrySet()) {
switch (targetWorkMode) {
case COLLECTALL:
- scheduleNextPolling(deviceContext, statisticsContext, new TimeCounter());
- for (final ItemLifeCycleSource lifeCycleSource : deviceContext.getItemLifeCycleSourceRegistry().getLifeCycleSources()) {
+ scheduleNextPolling(conductor.getDeviceContext(entry.getKey()).getDeviceState(), entry.getKey(), entry.getValue(), new TimeCounter());
+ for (final ItemLifeCycleSource lifeCycleSource : conductor.getDeviceContext(entry.getKey()).getItemLifeCycleSourceRegistry().getLifeCycleSources()) {
lifeCycleSource.setItemLifecycleListener(null);
}
break;
case FULLYDISABLED:
- final Optional<Timeout> pollTimeout = statisticsContext.getPollTimeout();
+ final Optional<Timeout> pollTimeout = entry.getValue().getPollTimeout();
if (pollTimeout.isPresent()) {
pollTimeout.get().cancel();
}
- for (final ItemLifeCycleSource lifeCycleSource : deviceContext.getItemLifeCycleSourceRegistry().getLifeCycleSources()) {
- lifeCycleSource.setItemLifecycleListener(statisticsContext.getItemLifeCycleListener());
+ for (final ItemLifeCycleSource lifeCycleSource : conductor.getDeviceContext(entry.getKey()).getItemLifeCycleSourceRegistry().getLifeCycleSources()) {
+ lifeCycleSource.setItemLifecycleListener(entry.getValue().getItemLifeCycleListener());
}
break;
default:
}
@Override
- public void startScheduling(final NodeId nodeId) {
+ public void startScheduling(final DeviceInfo deviceInfo) {
if (shuttingDownStatisticsPolling) {
- LOG.info("Statistics are shut down for device: {}", nodeId);
+ LOG.info("Statistics are shut down for device: {}", deviceInfo.getNodeId());
return;
}
- final StatisticsContext statisticsContext = contexts.get(nodeId);
+ final StatisticsContext statisticsContext = contexts.get(deviceInfo);
if (statisticsContext == null) {
- LOG.warn("Statistics context not found for device: {}", nodeId);
+ LOG.warn("Statistics context not found for device: {}", deviceInfo.getNodeId());
return;
}
if (statisticsContext.isSchedulingEnabled()) {
- LOG.debug("Statistics scheduling is already enabled for device: {}", nodeId);
+ LOG.debug("Statistics scheduling is already enabled for device: {}", deviceInfo.getNodeId());
return;
}
- LOG.info("Scheduling statistics poll for device: {}", nodeId);
- final DeviceContext deviceContext = conductor.getDeviceContext(nodeId);
-
- if (deviceContext == null) {
- LOG.warn("Device context not found for device: {}", nodeId);
- return;
- }
+ LOG.info("Scheduling statistics poll for device: {}", deviceInfo.getNodeId());
statisticsContext.setSchedulingEnabled(true);
- scheduleNextPolling(deviceContext, statisticsContext, new TimeCounter());
+ scheduleNextPolling(conductor.getDeviceContext(deviceInfo).getDeviceState(), deviceInfo, statisticsContext, new TimeCounter());
}
@Override
- public void stopScheduling(final NodeId nodeId) {
- LOG.debug("Stopping statistics scheduling for device: {}", nodeId);
- final StatisticsContext statisticsContext = contexts.get(nodeId);
+ public void stopScheduling(final DeviceInfo deviceInfo) {
+ LOG.debug("Stopping statistics scheduling for device: {}", deviceInfo.getNodeId());
+ final StatisticsContext statisticsContext = contexts.get(deviceInfo);
if (statisticsContext == null) {
- LOG.warn("Statistics context not found for device: {}", nodeId);
+ LOG.warn("Statistics context not found for device: {}", deviceInfo.getNodeId());
return;
}
public void setDeviceTerminationPhaseHandler(final DeviceTerminationPhaseHandler handler) {
this.deviceTerminPhaseHandler = handler;
}
+
+ @Override
+ public <T extends OFPContext> T gainContext(DeviceInfo deviceInfo) {
+ return (T) contexts.get(deviceInfo);
+ }
}
final TranslatorKey translatorKey = new TranslatorKey(mpReply.getVersion(), MultipartReplyAggregateCase.class.getName());
final MessageTranslator<MultipartReply, AggregatedFlowStatistics> messageTranslator = translatorLibrary.lookupTranslator(translatorKey);
- final AggregatedFlowStatistics flowStatistics = messageTranslator.translate(mpReply, getDeviceContext().getDeviceState(), null);
+ final AggregatedFlowStatistics flowStatistics = messageTranslator.translate(mpReply, getDeviceInfo(), null);
final AggregateFlowStatisticsUpdateBuilder notification = new AggregateFlowStatisticsUpdateBuilder(flowStatistics)
- .setId(getDeviceContext().getDeviceState().getNodeId())
+ .setId(getDeviceInfo().getNodeId())
.setMoreReplies(Boolean.FALSE)
.setTransactionId(emulatedTxId);
@Override
public FlowsStatisticsUpdate transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return FlowStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return FlowStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
@Override
public FlowsStatisticsUpdate transformToNotification(List<MultipartReply> mpResult, TransactionId emulatedTxId) {
- return FlowStatisticsToNotificationTransformer.transformToNotification(mpResult, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return FlowStatisticsToNotificationTransformer.transformToNotification(mpResult, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
@Override
public GroupStatisticsUpdated transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return GroupStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return GroupStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), emulatedTxId);
}
}
@Override
public MeterConfigStatsUpdated transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
MeterConfigStatsUpdatedBuilder message = new MeterConfigStatsUpdatedBuilder();
- message.setId(getDeviceContext().getDeviceState().getNodeId());
+ message.setId(getDeviceInfo().getNodeId());
message.setMoreReplies(Boolean.FALSE);
message.setTransactionId(emulatedTxId);
@Override
public MeterStatisticsUpdated transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return MeterStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return MeterStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
@Override
public NodeConnectorStatisticsUpdate transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return NodeConnectorStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext(), getOfVersion(), emulatedTxId);
+ return NodeConnectorStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
@Override
public QueueStatisticsUpdate transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return QueueStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return QueueStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
@Override
public QueueStatisticsUpdate transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return QueueStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return QueueStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
// convert and inject match
final short version = getVersion();
- final DeviceContext deviceContext = getDeviceContext();
MatchReactor.getInstance().convert(input.getMatch(), version, mprFlowRequestBuilder,
- deviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId());
+ getDeviceInfo().getDatapathId());
// Set request body to main multipart request
multipartRequestFlowCaseBuilder.setMultipartRequestFlow(mprFlowRequestBuilder.build());
@Override
public FlowsStatisticsUpdate transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return FlowStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return FlowStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
@Override
public GroupDescStatsUpdated transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
GroupDescStatsUpdatedBuilder notification = new GroupDescStatsUpdatedBuilder();
- notification.setId(getDeviceContext().getDeviceState().getNodeId());
+ notification.setId(getDeviceInfo().getNodeId());
notification.setMoreReplies(Boolean.FALSE);
notification.setTransactionId(emulatedTxId);
Preconditions.checkArgument(mpSize == 1, "unexpected (!=1) mp-reply size received: {}", mpSize);
GroupFeaturesUpdatedBuilder notification = new GroupFeaturesUpdatedBuilder();
- notification.setId(getDeviceContext().getDeviceState().getNodeId());
+ notification.setId(getDeviceInfo().getNodeId());
notification.setMoreReplies(Boolean.FALSE);
notification.setTransactionId(emulatedTxId);
@Override
public GroupStatisticsUpdated transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return GroupStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return GroupStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), emulatedTxId);
}
}
@Override
protected OfHeader buildRequest(final Xid xid, final GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
- final DeviceContext deviceContext = getDeviceContext();
final MultipartRequestAggregateCaseBuilder multipartRequestAggregateCaseBuilder = new MultipartRequestAggregateCaseBuilder();
final MultipartRequestAggregateBuilder mprAggregateRequestBuilder = new MultipartRequestAggregateBuilder();
final short tableId = MoreObjects.firstNonNull(input.getTableId(), OFConstants.OFPTT_ALL).shortValue();
Preconditions.checkArgument(mpSize == 1, "unexpected (!=1) mp-reply size received: {}", mpSize);
MeterFeaturesUpdatedBuilder notification = new MeterFeaturesUpdatedBuilder();
- notification.setId(getDeviceContext().getDeviceState().getNodeId());
+ notification.setId(getDeviceInfo().getNodeId());
notification.setMoreReplies(Boolean.FALSE);
notification.setTransactionId(emulatedTxId);
@Override
public MeterStatisticsUpdated transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return MeterStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return MeterStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
@Override
public QueueStatisticsUpdate transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return QueueStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext().getDeviceState(), getOfVersion(), emulatedTxId);
+ return QueueStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
import java.util.List;
import java.util.concurrent.Future;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
new Function<RpcResult<List<MultipartReply>>, RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>>() {
@Override
public RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput> apply(final RpcResult<List<MultipartReply>> input) {
- final DeviceContext deviceContext = matchingFlowsInTable.getDeviceContext();
+ final DeviceInfo deviceInfo = matchingFlowsInTable.getDeviceInfo();
final RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput> rpcResult;
if (input.isSuccessful()) {
MultipartReply reply = input.getResult().get(0);
List<AggregatedFlowStatistics> aggregStats = new ArrayList<AggregatedFlowStatistics>();
for (MultipartReply multipartReply : input.getResult()) {
- aggregStats.add(messageTranslator.translate(multipartReply, deviceContext.getDeviceState(), null));
+ aggregStats.add(messageTranslator.translate(multipartReply, deviceInfo, null));
}
GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder getAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder =
@Override
public FlowTableStatisticsUpdate transformToNotification(List<MultipartReply> mpReplyList, TransactionId emulatedTxId) {
FlowTableStatisticsUpdateBuilder notification = new FlowTableStatisticsUpdateBuilder();
- notification.setId(getDeviceContext().getDeviceState().getNodeId());
+ notification.setId(getDeviceInfo().getNodeId());
notification.setMoreReplies(Boolean.FALSE);
notification.setTransactionId(emulatedTxId);
@Override
public NodeConnectorStatisticsUpdate transformToNotification(List<MultipartReply> result, TransactionId emulatedTxId) {
- return NodeConnectorStatisticsToNotificationTransformer.transformToNotification(result, getDeviceContext(), getOfVersion(), emulatedTxId);
+ return NodeConnectorStatisticsToNotificationTransformer.transformToNotification(result, getDeviceInfo(), getOfVersion(), emulatedTxId);
}
}
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.List;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.FlowStatsResponseConvertor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
/**
* @param mpResult raw multipart response from device
- * @param deviceState device state
+ * @param deviceInfo device state
* @param ofVersion device version
* @param emulatedTxId
* @return notification containing flow stats
*/
public static FlowsStatisticsUpdate transformToNotification(final List<MultipartReply> mpResult,
- final DeviceState deviceState,
+ final DeviceInfo deviceInfo,
final OpenflowVersion ofVersion,
final TransactionId emulatedTxId) {
final FlowsStatisticsUpdateBuilder notification = new FlowsStatisticsUpdateBuilder();
final List<FlowAndStatisticsMapList> statsList = new ArrayList<>();
- notification.setId(deviceState.getNodeId());
+ notification.setId(deviceInfo.getNodeId());
notification.setFlowAndStatisticsMapList(statsList);
notification.setMoreReplies(Boolean.FALSE);
notification.setTransactionId(emulatedTxId);
MultipartReplyFlow replyBody = caseBody.getMultipartReplyFlow();
List<FlowAndStatisticsMapList> outStatsItem = flowStatsConvertor.toSALFlowStatsList(
replyBody.getFlowStats(),
- deviceState.getFeatures().getDatapathId(),
+ deviceInfo.getDatapathId(),
ofVersion);
statsList.addAll(outStatsItem);
}
import java.util.ArrayList;
import java.util.List;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
-import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.GroupStatsResponseConvertor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
/**
* @param mpReplyList raw multipart response from device
- * @param deviceState device state
- * @param ofVersion device version
+ * @param deviceInfo device state
* @param emulatedTxId
* @return notification containing flow stats
*/
public static GroupStatisticsUpdated transformToNotification(final List<MultipartReply> mpReplyList,
- final DeviceState deviceState,
- final OpenflowVersion ofVersion,
+ final DeviceInfo deviceInfo,
final TransactionId emulatedTxId) {
GroupStatisticsUpdatedBuilder notification = new GroupStatisticsUpdatedBuilder();
- notification.setId(deviceState.getNodeId());
+ notification.setId(deviceInfo.getNodeId());
notification.setMoreReplies(Boolean.FALSE);
notification.setTransactionId(emulatedTxId);
import java.util.ArrayList;
import java.util.List;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.MeterStatsResponseConvertor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
/**
* @param mpReplyList raw multipart response from device
- * @param deviceState device state
+ * @param deviceInfo device state
* @param ofVersion device version
* @param emulatedTxId
* @return notification containing flow stats
*/
public static MeterStatisticsUpdated transformToNotification(final List<MultipartReply> mpReplyList,
- final DeviceState deviceState,
+ final DeviceInfo deviceInfo,
final OpenflowVersion ofVersion,
final TransactionId emulatedTxId) {
MeterStatisticsUpdatedBuilder notification = new MeterStatisticsUpdatedBuilder();
- notification.setId(deviceState.getNodeId());
+ notification.setId(deviceInfo.getNodeId());
notification.setMoreReplies(Boolean.FALSE);
notification.setTransactionId(emulatedTxId);
import com.google.common.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.List;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
/**
* @param mpReplyList raw multipart response from device
- * @param deviceContext device context
+ * @param deviceInfo device basic info
* @param ofVersion device version
* @param emulatedTxId
* @return notification containing flow stats
*/
public static NodeConnectorStatisticsUpdate transformToNotification(final List<MultipartReply> mpReplyList,
- final DeviceContext deviceContext,
+ final DeviceInfo deviceInfo,
final OpenflowVersion ofVersion,
final TransactionId emulatedTxId) {
NodeConnectorStatisticsUpdateBuilder notification = new NodeConnectorStatisticsUpdateBuilder();
- notification.setId(deviceContext.getDeviceState().getNodeId());
+ notification.setId(deviceInfo.getNodeId());
notification.setMoreReplies(Boolean.FALSE);
notification.setTransactionId(emulatedTxId);
MultipartReplyPortStats replyBody = caseBody.getMultipartReplyPortStats();
for (PortStats portStats : replyBody.getPortStats()) {
NodeConnectorStatisticsAndPortNumberMapBuilder statsBuilder =
- processSingleNodeConnectorStats(deviceContext, ofVersion, portStats);
+ processSingleNodeConnectorStats(deviceInfo, ofVersion, portStats);
notification.getNodeConnectorStatisticsAndPortNumberMap().add(statsBuilder.build());
}
}
}
@VisibleForTesting
- static NodeConnectorStatisticsAndPortNumberMapBuilder processSingleNodeConnectorStats(DeviceContext deviceContext, OpenflowVersion ofVersion, PortStats portStats) {
+ static NodeConnectorStatisticsAndPortNumberMapBuilder processSingleNodeConnectorStats(DeviceInfo deviceInfo, OpenflowVersion ofVersion, PortStats portStats) {
NodeConnectorStatisticsAndPortNumberMapBuilder statsBuilder =
new NodeConnectorStatisticsAndPortNumberMapBuilder();
statsBuilder.setNodeConnectorId(
InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
- deviceContext.getDeviceState().getFeatures().getDatapathId(),
+ deviceInfo.getDatapathId(),
portStats.getPortNo(), ofVersion));
BytesBuilder bytesBuilder = new BytesBuilder();
import java.util.ArrayList;
import java.util.List;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
/**
* @param mpReplyList raw multipart response from device
- * @param deviceState device state
+ * @param deviceInfo device state
* @param ofVersion device version
* @param emulatedTxId
* @return notification containing flow stats
*/
public static QueueStatisticsUpdate transformToNotification(final List<MultipartReply> mpReplyList,
- final DeviceState deviceState,
+ final DeviceInfo deviceInfo,
final OpenflowVersion ofVersion,
final TransactionId emulatedTxId) {
QueueStatisticsUpdateBuilder notification = new QueueStatisticsUpdateBuilder();
- notification.setId(deviceState.getNodeId());
+ notification.setId(deviceInfo.getNodeId());
notification.setMoreReplies(Boolean.FALSE);
notification.setTransactionId(emulatedTxId);
new QueueIdAndStatisticsMapBuilder();
statsBuilder.setNodeConnectorId(
InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(
- deviceState.getFeatures().getDatapathId(),
+ deviceInfo.getDatapathId(),
queueStats.getPortNo(), ofVersion));
statsBuilder.setTransmissionErrors(new Counter64(queueStats.getTxErrors()));
statsBuilder.setTransmittedBytes(new Counter64(queueStats.getTxBytes()));
@Override
public Future<RpcResult<List<MultipartReply>>> getStatisticsOfType(final EventIdentifier eventIdentifier, final MultipartType type) {
- LOG.debug("Getting statistics (onTheFly) for node {} of type {}", getNodeId(), type);
+ LOG.debug("Getting statistics (onTheFly) for node {} of type {}", getDeviceInfo().getNodeId(), type);
EventsTimeCounter.markStart(eventIdentifier);
setEventIdentifier(eventIdentifier);
return handleServiceCall(type);
@Override
public Future<RpcResult<List<MultipartReply>>> getStatisticsOfType(final EventIdentifier eventIdentifier, final MultipartType type) {
- LOG.debug("Getting statistics for node {} of type {}", getNodeId(), type);
+ LOG.debug("Getting statistics for node {} of type {}", getDeviceInfo().getNodeId(), type);
EventsTimeCounter.markStart(eventIdentifier);
setEventIdentifier(eventIdentifier);
return handleServiceCall(type);
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
+import java.util.concurrent.Future;
+import javax.annotation.Nullable;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.device.Xid;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import javax.annotation.Nullable;
-import java.util.List;
-import java.util.concurrent.Future;
-
/**
* The abstract direct statistics service.
* This abstract service provides wrappers and tools for all other derived statistics services.
if (input.isSuccessful()) {
storeStatistics(input.getResult());
- getDeviceContext().submitTransaction(); // TODO: If submitTransaction will ever return future, chain it
+ getTxFacade().submitTransaction(); // TODO: If submitTransaction will ever return future, chain it
}
return Futures.immediateFuture(input);
final ListenableFuture<RpcResult<List<MultipartReply>>> rpcReply = handleServiceCall(input);
ListenableFuture<RpcResult<O>> rpcResult = Futures.transform(rpcReply, resultTransformFunction);
- if (input.isStoreStats()) {
+ if (Boolean.TRUE.equals(input.isStoreStats())) {
rpcResult = Futures.transform(rpcResult, resultStoreFunction);
}
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import java.util.ArrayList;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.flow._case.MultipartRequestFlowBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* The Flow direct statistics service.
*/
@Override
protected void storeStatistics(GetFlowStatisticsOutput output) throws Exception {
- final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceContext()
- .getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+ final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceInfo().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
for (final FlowAndStatisticsMapList flowStatistics : output.getFlowAndStatisticsMapList()) {
final FlowId flowId = generateFlowId(flowStatistics);
.child(Table.class, new TableKey(flowStatistics.getTableId()))
.child(Flow.class, flowKey);
- getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, flowStatisticsPath, flowBuilder.build());
+ getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, flowStatisticsPath, flowBuilder.build());
}
}
final short tableId = flowStatistics.getTableId();
final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(flowBuilder.build());
- return getDeviceContext().getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey, tableId);
+ return getDeviceRegistry().getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey, tableId);
}
}
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import java.util.ArrayList;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.group._case.MultipartRequestGroupBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* The Group direct statistics service.
*/
@Override
protected void storeStatistics(GetGroupStatisticsOutput output) throws Exception {
- final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceContext()
- .getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+ final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceInfo().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
for (final GroupStats groupStatistics : output.getGroupStats()) {
final InstanceIdentifier<GroupStatistics> groupStatisticsPath = nodePath
.child(GroupStatistics.class);
final GroupStatistics stats = new GroupStatisticsBuilder(groupStatistics).build();
- getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, groupStatisticsPath, stats);
+ getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, groupStatisticsPath, stats);
}
}
}
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import java.util.ArrayList;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.meter._case.MultipartRequestMeterBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* The Meter direct statistics service.
*/
@Override
protected void storeStatistics(GetMeterStatisticsOutput output) throws Exception {
- final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceContext()
- .getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+ final InstanceIdentifier<FlowCapableNode> nodePath = getDeviceInfo().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
for (final MeterStats meterStatistics : output.getMeterStats()) {
final InstanceIdentifier<MeterStatistics> meterPath = nodePath
.child(MeterStatistics.class);
final MeterStatistics stats = new MeterStatisticsBuilder(meterStatistics).build();
- getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, meterPath, stats);
+ getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, meterPath, stats);
}
}
}
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import java.util.ArrayList;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* The Node connector direct statistics service.
*/
@Override
protected void storeStatistics(GetNodeConnectorStatisticsOutput output) throws Exception {
- final InstanceIdentifier<Node> nodePath = getDeviceContext().getDeviceState().getNodeInstanceIdentifier();
+ final InstanceIdentifier<Node> nodePath = getDeviceInfo().getNodeInstanceIdentifier();
for (final NodeConnectorStatisticsAndPortNumberMap nodeConnectorStatistics : output.getNodeConnectorStatisticsAndPortNumberMap()) {
final InstanceIdentifier<FlowCapableNodeConnectorStatistics> nodeConnectorPath = nodePath
.child(FlowCapableNodeConnectorStatistics.class);
final FlowCapableNodeConnectorStatistics stats = new FlowCapableNodeConnectorStatisticsBuilder(nodeConnectorStatistics).build();
- getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, nodeConnectorPath, stats);
+ getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, nodeConnectorPath, stats);
}
}
}
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import java.util.Optional;
+import java.util.concurrent.Future;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsInput;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import java.util.Optional;
-import java.util.concurrent.Future;
-
/**
* The Opendaylight direct statistics service.
* This service handles RPC requests, sends them to registered handlers and returns their replies.
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import java.util.ArrayList;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* The Queue direct statistics service.
*/
@Override
protected void storeStatistics(GetQueueStatisticsOutput output) throws Exception {
- final InstanceIdentifier<Node> nodePath = getDeviceContext().getDeviceState().getNodeInstanceIdentifier();
+ final InstanceIdentifier<Node> nodePath = getDeviceInfo().getNodeInstanceIdentifier();
for (final QueueIdAndStatisticsMap queueStatistics : output.getQueueIdAndStatisticsMap()) {
if (queueStatistics.getQueueId() != null) {
.setQueueId(queueStatistics.getQueueId())
.addAugmentation(FlowCapableNodeConnectorQueueStatisticsData.class, statBuild.build()).build();
- getDeviceContext().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, queueStatisticsPath, stats);
+ getTxFacade().writeToTransactionWithParentsSlow(LogicalDatastoreType.OPERATIONAL, queueStatisticsPath, stats);
}
}
}
package org.opendaylight.openflowplugin.impl.translator;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64;
*/
public class AggregatedFlowStatisticsTranslator implements MessageTranslator<MultipartReply, AggregatedFlowStatistics> {
@Override
- public AggregatedFlowStatistics translate(final MultipartReply input, final DeviceState deviceState, final Object connectionDistinguisher) {
+ public AggregatedFlowStatistics translate(final MultipartReply input, final DeviceInfo deviceInfo, final Object connectionDistinguisher) {
AggregatedFlowStatisticsBuilder aggregatedFlowStatisticsBuilder = new AggregatedFlowStatisticsBuilder();
MultipartReplyAggregateCase caseBody = (MultipartReplyAggregateCase)input.getMultipartReplyBody();
*/
package org.opendaylight.openflowplugin.impl.translator;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchConvertorImpl;
public class FlowRemovedTranslator implements MessageTranslator<FlowRemoved, org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved> {
@Override
- public org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved translate(FlowRemoved input, DeviceState deviceState, Object connectionDistinguisher) {
+ public org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved translate(FlowRemoved input, DeviceInfo deviceInfo, Object connectionDistinguisher) {
FlowRemovedBuilder flowRemovedBld = new FlowRemovedBuilder()
- .setMatch(translateMatch(input, deviceState).build())
+ .setMatch(translateMatch(input, deviceInfo).build())
.setCookie(new FlowCookie(input.getCookie()))
- .setNode(new NodeRef(deviceState.getNodeInstanceIdentifier()))
+ .setNode(new NodeRef(deviceInfo.getNodeInstanceIdentifier()))
.setPriority(input.getPriority())
- .setTableId(input.getTableId().getValue().shortValue());
+ .setTableId(translateTableId(input));
return flowRemovedBld.build();
}
- protected MatchBuilder translateMatch(FlowRemoved flowRemoved, DeviceState deviceState) {
+ protected MatchBuilder translateMatch(FlowRemoved flowRemoved, DeviceInfo deviceInfo) {
return MatchConvertorImpl.fromOFMatchToSALMatch(flowRemoved.getMatch(),
- deviceState.getFeatures().getDatapathId(), OpenflowVersion.OF13);
+ deviceInfo.getDatapathId(), OpenflowVersion.OF13);
+ }
+
+ /**
+ * Translate the table ID in the FLOW_REMOVED message to SAL table ID.
+ *
+ * @param flowRemoved FLOW_REMOVED message.
+ * @return SAL table ID.
+ */
+ protected Short translateTableId(FlowRemoved flowRemoved) {
+ return flowRemoved.getTableId().getValue().shortValue();
}
}
package org.opendaylight.openflowplugin.impl.translator;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchConvertorImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
public class FlowRemovedV10Translator extends FlowRemovedTranslator {
@Override
- protected MatchBuilder translateMatch(FlowRemoved flowRemoved, DeviceState deviceState) {
+ protected MatchBuilder translateMatch(FlowRemoved flowRemoved, DeviceInfo deviceInfo) {
return MatchConvertorImpl.fromOFMatchV10ToSALMatch(flowRemoved.getMatchV10(),
- deviceState.getFeatures().getDatapathId(), OpenflowVersion.OF10);
+ deviceInfo.getDatapathId(), OpenflowVersion.OF10);
+ }
+
+ /**
+ * Always returns zero because OF10 FLOW_REMOVED doesn't contain table ID.
+ *
+ * @param flowRemoved FLOW_REMOVED message.
+ * @return Zero.
+ */
+ @Override
+ protected Short translateTableId(FlowRemoved flowRemoved) {
+ return Short.valueOf((short)0);
}
}
import com.google.common.annotations.VisibleForTesting;
import java.math.BigInteger;
-import java.util.List;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.extension.api.AugmentTuple;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.InPortCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceivedBuilder;
*/
public class PacketReceivedTranslator implements MessageTranslator<PacketInMessage, PacketReceived> {
@Override
- public PacketReceived translate(final PacketInMessage input, final DeviceState deviceState, final Object connectionDistinguisher) {
+ public PacketReceived translate(final PacketInMessage input, final DeviceInfo deviceInfo, final Object connectionDistinguisher) {
PacketReceivedBuilder packetReceivedBuilder = new PacketReceivedBuilder();
- BigInteger datapathId = deviceState.getFeatures().getDatapathId();
+ BigInteger datapathId = deviceInfo.getDatapathId();
// TODO: connection cookie from connection distinguisher
// packetReceivedBuilder.setConnectionCookie(new ConnectionCookie(input.getCookie().longValue()));
}
// Try to create the NodeConnectorRef
- BigInteger dataPathId = deviceState.getFeatures().getDatapathId();
+ BigInteger dataPathId = deviceInfo.getDatapathId();
NodeConnectorRef nodeConnectorRef = NodeConnectorRefToPortTranslator.toNodeConnectorRef(input, dataPathId);
// If we was able to create NodeConnectorRef, use it
import java.util.Collections;
import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.openflow.md.util.PortTranslatorUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
@Override
public FlowCapableNodeConnector translate(final PortGrouping input,
- final DeviceState deviceState, final Object connectionDistinguisher) {
+ final DeviceInfo deviceInfo, final Object connectionDistinguisher) {
final FlowCapableNodeConnectorBuilder builder = new FlowCapableNodeConnectorBuilder();
//OF1.0
- if (deviceState.getVersion() == OFConstants.OFP_VERSION_1_0) {
+ if (deviceInfo.getVersion() == OFConstants.OFP_VERSION_1_0) {
builder.setAdvertisedFeatures(PortTranslatorUtil.translatePortFeatures(input.getAdvertisedFeaturesV10()));
builder.setConfiguration(PortTranslatorUtil.translatePortConfig(input.getConfigV10()));
builder.setCurrentFeature(PortTranslatorUtil.translatePortFeatures(input.getCurrentFeaturesV10()));
builder.setPeerFeatures(PortTranslatorUtil.translatePortFeatures(input.getPeerFeaturesV10()));
builder.setState(PortTranslatorUtil.translatePortState(input.getStateV10()));
builder.setSupported(PortTranslatorUtil.translatePortFeatures(input.getSupportedFeaturesV10()));
- } else if (deviceState.getVersion() == OFConstants.OFP_VERSION_1_3) {
+ } else if (deviceInfo.getVersion() == OFConstants.OFP_VERSION_1_3) {
builder.setAdvertisedFeatures(PortTranslatorUtil.translatePortFeatures(input.getAdvertisedFeatures()));
builder.setConfiguration(PortTranslatorUtil.translatePortConfig(input.getConfig()));
builder.setCurrentFeature(PortTranslatorUtil.translatePortFeatures(input.getCurrentFeatures()));
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import java.math.BigInteger;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Collection;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
public static ListenableFuture<Void> initializeNodeInformation(final DeviceContext deviceContext, final boolean switchFeaturesMandatory) {
Preconditions.checkArgument(deviceContext != null);
final DeviceState deviceState = Preconditions.checkNotNull(deviceContext.getDeviceState());
+ final DeviceInfo deviceInfo = deviceContext.getDeviceInfo();
final ConnectionContext connectionContext = Preconditions.checkNotNull(deviceContext.getPrimaryConnectionContext());
- final short version = deviceState.getVersion();
- LOG.trace("initalizeNodeInformation for node {}", deviceState.getNodeId());
+ final short version = deviceInfo.getVersion();
+ LOG.trace("initalizeNodeInformation for node {}", deviceInfo.getNodeId());
final SettableFuture<Void> returnFuture = SettableFuture.<Void>create();
addNodeToOperDS(deviceContext, returnFuture);
final ListenableFuture<List<RpcResult<List<MultipartReply>>>> deviceFeaturesFuture;
// create empty tables after device description is processed
chainTableTrunkWriteOF10(deviceContext, deviceFeaturesFuture);
- final short ofVersion = deviceContext.getDeviceState().getVersion();
+ final short ofVersion = deviceInfo.getVersion();
final TranslatorKey translatorKey = new TranslatorKey(ofVersion, PortGrouping.class.getName());
final MessageTranslator<PortGrouping, FlowCapableNodeConnector> translator = deviceContext.oook()
.lookupTranslator(translatorKey);
- final BigInteger dataPathId = deviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId();
+ final BigInteger dataPathId = deviceContext.getDeviceInfo().getDatapathId();
for (final PortGrouping port : connectionContext.getFeatures().getPhyPort()) {
- final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, deviceContext.getDeviceState(), null);
+ final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, deviceContext.getDeviceInfo(), null);
final NodeConnectorId nodeConnectorId = NodeStaticReplyTranslatorUtil.nodeConnectorId(
dataPathId.toString(), port.getPortNo(), ofVersion);
ncBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class,
new FlowCapableNodeConnectorStatisticsDataBuilder().build());
final NodeConnector connector = ncBuilder.build();
- final InstanceIdentifier<NodeConnector> connectorII = deviceState.getNodeInstanceIdentifier().child(
+ final InstanceIdentifier<NodeConnector> connectorII = deviceInfo.getNodeInstanceIdentifier().child(
NodeConnector.class, connector.getKey());
try {
deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, connectorII, connector);
} catch (final Exception e) {
- LOG.debug("Failed to write node {} to DS ", deviceContext.getDeviceState().getNodeId().toString(),
+ LOG.debug("Failed to write node {} to DS ", deviceInfo.getNodeId().toString(),
e);
}
}
} else if (OFConstants.OFP_VERSION_1_3 == version) {
final Capabilities capabilities = connectionContext.getFeatures().getCapabilities();
- LOG.debug("Setting capabilities for device {}", deviceContext.getDeviceState().getNodeId());
+ LOG.debug("Setting capabilities for device {}", deviceInfo.getNodeId());
DeviceStateUtil.setDeviceStateBasedOnV13Capabilities(deviceState, capabilities);
deviceFeaturesFuture = createDeviceFeaturesForOF13(deviceContext, deviceState, switchFeaturesMandatory);
} else {
Futures.addCallback(deviceFeaturesFuture, new FutureCallback<List<RpcResult<List<MultipartReply>>>>() {
@Override
public void onSuccess(final List<RpcResult<List<MultipartReply>>> result) {
- LOG.debug("All init data for node {} is in submited.", deviceState.getNodeId());
+ LOG.debug("All init data for node {} is in submited.", deviceInfo.getNodeId());
returnFuture.set(null);
}
// FIXME : remove session
LOG.trace("Device capabilities gathering future failed.");
LOG.trace("more info in exploration failure..", t);
- LOG.debug("All init data for node {} was not submited correctly - connection has to go down.", deviceState.getNodeId());
+ LOG.debug("All init data for node {} was not submited correctly - connection has to go down.", deviceInfo.getNodeId());
returnFuture.setException(t);
}
});
private static void addNodeToOperDS(final DeviceContext deviceContext, final SettableFuture<Void> future) {
Preconditions.checkArgument(deviceContext != null);
final DeviceState deviceState = deviceContext.getDeviceState();
- final NodeBuilder nodeBuilder = new NodeBuilder().setId(deviceState.getNodeId()).setNodeConnector(
+ final NodeBuilder nodeBuilder = new NodeBuilder().setId(deviceContext.getDeviceInfo().getNodeId()).setNodeConnector(
Collections.<NodeConnector>emptyList());
try {
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, deviceState.getNodeInstanceIdentifier(),
+ deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(),
nodeBuilder.build());
} catch (final Exception e) {
- LOG.warn("Failed to write node {} to DS ", deviceState.getNodeId(), e);
+ LOG.warn("Failed to write node {} to DS ", deviceContext.getDeviceInfo().getNodeId(), e);
future.cancel(true);
}
}
private static ListenableFuture<List<RpcResult<List<MultipartReply>>>> createDeviceFeaturesForOF10(
final DeviceContext deviceContext, final DeviceState deviceState) {
final ListenableFuture<RpcResult<List<MultipartReply>>> replyDesc = getNodeStaticInfo(MultipartType.OFPMPDESC,
- deviceContext, deviceState.getNodeInstanceIdentifier(), deviceState.getVersion());
+ deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
return Futures.allAsList(Arrays.asList(replyDesc));
}
final DeviceContext deviceContext, final DeviceState deviceState, final boolean switchFeaturesMandatory) {
final ListenableFuture<RpcResult<List<MultipartReply>>> replyDesc = getNodeStaticInfo(MultipartType.OFPMPDESC,
- deviceContext, deviceState.getNodeInstanceIdentifier(), deviceState.getVersion());
+ deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
//first process description reply, write data to DS and write consequent data if successful
return Futures.transform(replyDesc,
final RpcResult<List<MultipartReply>> rpcResult) throws Exception {
translateAndWriteReply(MultipartType.OFPMPDESC, deviceContext,
- deviceState.getNodeInstanceIdentifier(), rpcResult.getResult());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), rpcResult.getResult());
final ListenableFuture<RpcResult<List<MultipartReply>>> replyMeterFeature = getNodeStaticInfo(
MultipartType.OFPMPMETERFEATURES, deviceContext,
- deviceState.getNodeInstanceIdentifier(), deviceState.getVersion());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
createSuccessProcessingCallback(MultipartType.OFPMPMETERFEATURES, deviceContext,
- deviceState.getNodeInstanceIdentifier(), replyMeterFeature);
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyMeterFeature);
final ListenableFuture<RpcResult<List<MultipartReply>>> replyGroupFeatures = getNodeStaticInfo(
MultipartType.OFPMPGROUPFEATURES, deviceContext,
- deviceState.getNodeInstanceIdentifier(), deviceState.getVersion());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
createSuccessProcessingCallback(MultipartType.OFPMPGROUPFEATURES, deviceContext,
- deviceState.getNodeInstanceIdentifier(), replyGroupFeatures);
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyGroupFeatures);
final ListenableFuture<RpcResult<List<MultipartReply>>> replyTableFeatures = getNodeStaticInfo(
MultipartType.OFPMPTABLEFEATURES, deviceContext,
- deviceState.getNodeInstanceIdentifier(), deviceState.getVersion());
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), deviceContext.getDeviceInfo().getVersion());
createSuccessProcessingCallback(MultipartType.OFPMPTABLEFEATURES, deviceContext,
- deviceState.getNodeInstanceIdentifier(), replyTableFeatures);
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyTableFeatures);
final ListenableFuture<RpcResult<List<MultipartReply>>> replyPortDescription = getNodeStaticInfo(
- MultipartType.OFPMPPORTDESC, deviceContext, deviceState.getNodeInstanceIdentifier(),
- deviceState.getVersion());
+ MultipartType.OFPMPPORTDESC, deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(),
+ deviceContext.getDeviceInfo().getVersion());
createSuccessProcessingCallback(MultipartType.OFPMPPORTDESC, deviceContext,
- deviceState.getNodeInstanceIdentifier(), replyPortDescription);
+ deviceContext.getDeviceInfo().getNodeInstanceIdentifier(), replyPortDescription);
if (switchFeaturesMandatory) {
return Futures.allAsList(Arrays.asList(replyMeterFeature, replyGroupFeatures,
replyTableFeatures, replyPortDescription));
final MultipartReplyPortDesc portDesc = ((MultipartReplyPortDescCase) body)
.getMultipartReplyPortDesc();
for (final PortGrouping port : portDesc.getPorts()) {
- final short ofVersion = dContext.getDeviceState().getVersion();
+ final short ofVersion = dContext.getDeviceInfo().getVersion();
final TranslatorKey translatorKey = new TranslatorKey(ofVersion, PortGrouping.class.getName());
final MessageTranslator<PortGrouping, FlowCapableNodeConnector> translator = dContext.oook()
.lookupTranslator(translatorKey);
- final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, dContext.getDeviceState(), null);
+ final FlowCapableNodeConnector fcNodeConnector = translator.translate(port, dContext.getDeviceInfo(), null);
final BigInteger dataPathId = dContext.getPrimaryConnectionContext().getFeatures()
.getDatapathId();
}
}
} catch (final Exception e) {
- LOG.debug("Failed to write node {} to DS ", dContext.getDeviceState().getNodeId().toString(), e);
+ LOG.debug("Failed to write node {} to DS ", dContext.getDeviceInfo().getNodeId().toString(), e);
}
}
private static void createEmptyFlowCapableNodeInDs(final DeviceContext deviceContext) {
final FlowCapableNodeBuilder flowCapableNodeBuilder = new FlowCapableNodeBuilder();
- final InstanceIdentifier<FlowCapableNode> fNodeII = deviceContext.getDeviceState().getNodeInstanceIdentifier()
+ final InstanceIdentifier<FlowCapableNode> fNodeII = deviceContext.getDeviceInfo().getNodeInstanceIdentifier()
.augmentation(FlowCapableNode.class);
try {
deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, fNodeII, flowCapableNodeBuilder.build());
} catch (final Exception e) {
- LOG.debug("Failed to write node {} to DS ", deviceContext.getDeviceState().getNodeId().toString(), e);
+ LOG.debug("Failed to write node {} to DS ", deviceContext.getDeviceInfo().getNodeId().toString(), e);
}
}
if (remoteAddress == null) {
LOG.warn("IP address of the node {} cannot be obtained. No connection with switch.", deviceContext
- .getDeviceState().getNodeId());
+ .getDeviceInfo().getNodeId());
return null;
}
LOG.info("IP address of switch is: {}", remoteAddress);
try {
dContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableII, tableBuilder.build());
} catch (final Exception e) {
- LOG.debug("Failed to write node {} to DS ", dContext.getDeviceState().getNodeId().toString(), e);
+ LOG.debug("Failed to write node {} to DS ", dContext.getDeviceInfo().getNodeId().toString(), e);
}
}
public void onSuccess(final RpcResult<List<MultipartReply>> rpcResult) {
final List<MultipartReply> result = rpcResult.getResult();
if (result != null) {
- LOG.info("Static node {} info: {} collected", deviceContext.getDeviceState().getNodeId(), type);
+ LOG.info("Static node {} info: {} collected", deviceContext.getDeviceInfo().getNodeId(), type);
translateAndWriteReply(type, deviceContext, nodeII, result);
} else {
final Iterator<RpcError> rpcErrorIterator = rpcResult.getErrors().iterator();
}
if (allSucceeded) {
createEmptyFlowCapableNodeInDs(deviceContext);
- makeEmptyTables(deviceContext, deviceContext.getDeviceState().getNodeInstanceIdentifier(),
- deviceContext.getDeviceState().getFeatures().getTables());
+ makeEmptyTables(deviceContext, deviceContext.getDeviceInfo().getNodeInstanceIdentifier(),
+ deviceContext.getPrimaryConnectionContext().getFeatures().getTables());
}
}
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.compatibility.Delegator;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
import org.opendaylight.openflowplugin.impl.services.FlowCapableTransactionServiceImpl;
import org.opendaylight.openflowplugin.impl.services.NodeConfigServiceImpl;
import org.opendaylight.openflowplugin.impl.services.PacketProcessingServiceImpl;
* @param newRole - role validation for {@link OfpRole#BECOMEMASTER}
*/
public static void registerMasterServices(@CheckForNull final RpcContext rpcContext,
- @CheckForNull final DeviceContext deviceContext, @CheckForNull final OfpRole newRole) {
+ @CheckForNull final DeviceContext deviceContext,
+ @CheckForNull final OfpRole newRole,
+ final ExtensionConverterProvider extensionConverterProvider) {
Preconditions.checkArgument(rpcContext != null);
Preconditions.checkArgument(deviceContext != null);
Preconditions.checkArgument(newRole != null);
rpcContext.registerRpcServiceImplementation(SalFlatBatchService.class, salFlatBatchService);
// TODO: experimenter symmetric and multipart message services
- rpcContext.registerRpcServiceImplementation(SalExperimenterMessageService.class, new SalExperimenterMessageServiceImpl(rpcContext, deviceContext));
+ rpcContext.registerRpcServiceImplementation(SalExperimenterMessageService.class,
+ new SalExperimenterMessageServiceImpl(rpcContext, deviceContext, extensionConverterProvider));
}
/**
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
+import java.math.BigInteger;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.in.port._case.InPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.InPortCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.in.port._case.InPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketIn;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.features.reply.PhyPort;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.math.BigInteger;
-import java.util.List;
-import java.util.Objects;
-
/**
* Created by Tomas Slusny on 23.3.2016.
*/
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.config.openflow.plugin.impl.rev150327;
+import com.google.common.reflect.AbstractInvocationHandler;
+import com.google.common.reflect.Reflection;
+import java.lang.reflect.Method;
+import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
-import org.opendaylight.openflowplugin.impl.OpenFlowPluginProviderImpl;
-import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegistratorProvider;
+import org.osgi.framework.BundleContext;
-public class OpenFlowProviderModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.config.openflow.plugin.impl.rev150327.AbstractOpenFlowProviderModule {
+/**
+ * @deprecated Replaced by blueprint wiring
+ */
+@Deprecated
+public class OpenFlowProviderModule extends AbstractOpenFlowProviderModule {
- private static final Logger LOG = LoggerFactory.getLogger(OpenFlowProviderModule.class);
+ private BundleContext bundleContext;
public OpenFlowProviderModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
super(identifier, dependencyResolver);
}
@Override
- public void customValidation() {
- // add custom validation form module attributes here.
+ public AutoCloseable createInstance() {
+ // The service is provided via blueprint so wait for and return it here for backwards compatibility.
+ String typeFilter = String.format("(type=%s)", getIdentifier().getInstanceName());
+ final WaitingServiceTracker<OpenFlowPluginProvider> tracker = WaitingServiceTracker.create(
+ OpenFlowPluginProvider.class, bundleContext, typeFilter);
+ final OpenFlowPluginProvider openflowPluginProvider = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
+
+ // We don't want to call close on the actual service as its life cycle is controlled by blueprint but
+ // we do want to close the tracker so create a proxy to override close appropriately.
+ return Reflection.newProxy(OpenFlowPluginProviderProxyInterface.class, new AbstractInvocationHandler() {
+ @Override
+ protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getName().equals("close")) {
+ tracker.close();
+ return null;
+ } else {
+ return method.invoke(openflowPluginProvider, args);
+ }
+ }
+ });
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
}
@Override
- public java.lang.AutoCloseable createInstance() {
- LOG.info("Initializing new OFP southbound.");
- OpenflowPortsUtil.init();
- final OpenFlowPluginProvider openflowPluginProvider = new OpenFlowPluginProviderImpl(getRpcRequestsQuota(), getGlobalNotificationQuota());
-
- openflowPluginProvider.setSwitchConnectionProviders(getOpenflowSwitchConnectionProviderDependency());
- openflowPluginProvider.setDataBroker(getDataBrokerDependency());
- openflowPluginProvider.setRpcProviderRegistry(getRpcRegistryDependency());
- openflowPluginProvider.setNotificationProviderService(getNotificationAdapterDependency());
- openflowPluginProvider.setNotificationPublishService(getNotificationPublishAdapterDependency());
- openflowPluginProvider.setSwitchFeaturesMandatory(getSwitchFeaturesMandatory());
- openflowPluginProvider.setIsStatisticsPollingOff(getIsStatisticsPollingOff());
- openflowPluginProvider.setEntityOwnershipService(getEntityOwnershipServiceDependency());
- openflowPluginProvider.setIsStatisticsRpcEnabled(getIsStatisticsRpcEnabled());
- openflowPluginProvider.setBarrierCountLimit(getBarrierCountLimit().getValue());
- openflowPluginProvider.setBarrierInterval(getBarrierIntervalTimeoutLimit().getValue());
- openflowPluginProvider.setEchoReplyTimeout(getEchoReplyTimeout().getValue());
-
- openflowPluginProvider.initialize();
-
- LOG.info("Configured values, StatisticsPollingOff:{}, SwitchFeaturesMandatory:{}, BarrierCountLimit:{}, BarrierTimeoutLimit:{}, EchoReplyTimeout:{}",
- getIsStatisticsPollingOff(), getSwitchFeaturesMandatory(), getBarrierCountLimit().getValue(),
- getBarrierIntervalTimeoutLimit().getValue(), getEchoReplyTimeout().getValue());
-
-
- return openflowPluginProvider;
+ public boolean canReuseInstance(AbstractOpenFlowProviderModule oldModule) {
+ return true;
}
+ private static interface OpenFlowPluginProviderProxyInterface extends OpenFlowPluginProvider,
+ OpenFlowPluginExtensionRegistratorProvider {
+ }
}
* Do not modify this file unless it is present under src/main directory
*/
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.config.openflow.plugin.impl.rev150327;
-public class OpenFlowProviderModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.config.openflow.plugin.impl.rev150327.AbstractOpenFlowProviderModuleFactory {
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.osgi.framework.BundleContext;
+
+/**
+ * @deprecated Replaced by blueprint wiring
+ */
+@Deprecated
+public class OpenFlowProviderModuleFactory extends AbstractOpenFlowProviderModuleFactory {
+ @Override
+ public OpenFlowProviderModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
+ OpenFlowProviderModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) {
+ OpenFlowProviderModule module = super.instantiateModule(instanceName, dependencyResolver, oldModule,
+ oldInstance, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+ @Override
+ public OpenFlowProviderModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
+ BundleContext bundleContext) {
+ OpenFlowProviderModule module = super.instantiateModule(instanceName, dependencyResolver, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="ofPluginProviderFactory" class="org.opendaylight.openflowplugin.impl.OpenFlowPluginProviderFactoryImpl"/>
+
+ <service ref="ofPluginProviderFactory" interface="org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProviderFactory"
+ odl:type="default"/>
+</blueprint>
\ No newline at end of file
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import com.google.common.util.concurrent.ListenableFuture;
import io.netty.util.HashedWheelTimer;
import io.netty.util.TimerTask;
+import java.math.BigInteger;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.ServiceChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
+import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
-
@RunWith(MockitoJUnitRunner.class)
public class LifecycleConductorImplTest {
@Mock
private ServiceChangeListener serviceChangeListener;
@Mock
- private ConcurrentHashMap<NodeId, ServiceChangeListener> serviceChangeListeners;
+ private ConcurrentHashMap<DeviceInfo, ServiceChangeListener> serviceChangeListeners;
@Mock
private DeviceContext deviceContext;
@Mock
private ListenableFuture<Void> listenableFuture;
@Mock
private StatisticsManager statisticsManager;
+ @Mock
+ private RpcManager rpcManager;
+ @Mock
+ private RpcContext rpcContext;
+ @Mock
+ private DeviceInfo deviceInfo;
private NodeId nodeId = new NodeId("openflow-junit:1");
private OfpRole ofpRole = OfpRole.NOCHANGE;
@Before
public void setUp() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(deviceContext);
- when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
lifecycleConductor = new LifecycleConductorImpl(messageIntelligenceAgency);
- lifecycleConductor.setSafelyDeviceManager(deviceManager);
- lifecycleConductor.setSafelyStatisticsManager(statisticsManager);
+ lifecycleConductor.setSafelyManager(deviceManager);
+ lifecycleConductor.setSafelyManager(statisticsManager);
+ lifecycleConductor.setSafelyManager(rpcManager);
- when(connectionContext.getFeatures()).thenReturn(featuresReply);
+ when(deviceManager.gainContext(Mockito.<DeviceInfo>any())).thenReturn(deviceContext);
+ when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
+ when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
+ when(rpcManager.gainContext(Mockito.<DeviceInfo>any())).thenReturn(rpcContext);
+ when(deviceInfo.getNodeId()).thenReturn(nodeId);
+ when(deviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
+ when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
+ when(rpcManager.gainContext(Mockito.<DeviceInfo>any())).thenReturn(rpcContext);
}
@Test
public void addOneTimeListenerWhenServicesChangesDoneTest() {
- lifecycleConductor.addOneTimeListenerWhenServicesChangesDone(serviceChangeListener, nodeId);
+ lifecycleConductor.addOneTimeListenerWhenServicesChangesDone(serviceChangeListener, deviceInfo);
assertEquals(false,lifecycleConductor.isServiceChangeListenersEmpty());
}
*/
@Test
public void notifyServiceChangeListenersTest1() {
- lifecycleConductor.notifyServiceChangeListeners(nodeId,true);
+ lifecycleConductor.notifyServiceChangeListeners(deviceInfo,true);
when(serviceChangeListeners.size()).thenReturn(0);
- verify(serviceChangeListeners,times(0)).remove(nodeId);
+ verify(serviceChangeListeners,times(0)).remove(deviceInfo);
}
/**
*/
@Test
public void notifyServiceChangeListenersTest2() {
- lifecycleConductor.addOneTimeListenerWhenServicesChangesDone(serviceChangeListener, nodeId);
+ lifecycleConductor.addOneTimeListenerWhenServicesChangesDone(serviceChangeListener, deviceInfo);
assertEquals(false,lifecycleConductor.isServiceChangeListenersEmpty());
- lifecycleConductor.notifyServiceChangeListeners(nodeId,true);
+ lifecycleConductor.notifyServiceChangeListeners(deviceInfo,true);
assertEquals(true,lifecycleConductor.isServiceChangeListenersEmpty());
}
*/
@Test
public void roleInitializationDoneTest1() {
- lifecycleConductor.addOneTimeListenerWhenServicesChangesDone(serviceChangeListener, nodeId);
- lifecycleConductor.roleInitializationDone(nodeId,false);
+ lifecycleConductor.addOneTimeListenerWhenServicesChangesDone(serviceChangeListener, deviceInfo);
+ lifecycleConductor.roleInitializationDone(deviceInfo,false);
verify(deviceContext,times(1)).shutdownConnection();
}
*/
@Test
public void roleInitializationDoneTest2() {
- lifecycleConductor.addOneTimeListenerWhenServicesChangesDone(serviceChangeListener, nodeId);
- lifecycleConductor.roleInitializationDone(nodeId,true);
+ lifecycleConductor.addOneTimeListenerWhenServicesChangesDone(serviceChangeListener, deviceInfo);
+ lifecycleConductor.roleInitializationDone(deviceInfo,true);
verify(deviceContext,times(0)).shutdownConnection();
}
*/
@Test
public void roleChangeOnDeviceTest1() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(null);
- lifecycleConductor.roleChangeOnDevice(nodeId,true,ofpRole,false);
+ when(deviceManager.gainContext(deviceInfo)).thenReturn(null);
+ lifecycleConductor.roleChangeOnDevice(deviceInfo,true,ofpRole,false);
verify(deviceContext,times(0)).shutdownConnection();
- lifecycleConductor.roleChangeOnDevice(nodeId,false,ofpRole,false);
+ lifecycleConductor.roleChangeOnDevice(deviceInfo,false,ofpRole,false);
verify(deviceContext,times(0)).shutdownConnection();
}
*/
@Test
public void roleChangeOnDeviceTest2() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(deviceContext);
- lifecycleConductor.roleChangeOnDevice(nodeId,false,ofpRole,false);
+ when(deviceManager.gainContext(deviceInfo)).thenReturn(deviceContext);
+ lifecycleConductor.roleChangeOnDevice(deviceInfo,false,ofpRole,false);
verify(deviceContext,times(1)).shutdownConnection();
}
*/
@Test
public void roleChangeOnDeviceTest3() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(deviceContext);
- lifecycleConductor.roleChangeOnDevice(nodeId,true,ofpRole,true);
+ when(deviceManager.gainContext(deviceInfo)).thenReturn(deviceContext);
+ lifecycleConductor.roleChangeOnDevice(deviceInfo,true,ofpRole,true);
verify(deviceContext,times(0)).shutdownConnection();
}
@Test
public void roleChangeOnDeviceTest4() {
when(deviceContext.getDeviceState()).thenReturn(deviceState);
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(deviceContext);
- when(deviceContext.onClusterRoleChange(null, OfpRole.BECOMEMASTER)).thenReturn(listenableFuture);
- lifecycleConductor.roleChangeOnDevice(nodeId,true,OfpRole.BECOMEMASTER,false);
- verify(statisticsManager).startScheduling(nodeId);
+ when(deviceManager.gainContext(deviceInfo)).thenReturn(deviceContext);
+ when(deviceManager.onClusterRoleChange(deviceInfo, OfpRole.BECOMEMASTER)).thenReturn(listenableFuture);
+ lifecycleConductor.roleChangeOnDevice(deviceInfo,true,OfpRole.BECOMEMASTER,false);
+ verify(statisticsManager).startScheduling(Mockito.<DeviceInfo>any());
}
/**
@Test
public void roleChangeOnDeviceTest5() {
when(deviceContext.getDeviceState()).thenReturn(deviceState);
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(deviceContext);
- when(deviceContext.onClusterRoleChange(null, OfpRole.BECOMESLAVE)).thenReturn(listenableFuture);
- lifecycleConductor.roleChangeOnDevice(nodeId,true,OfpRole.BECOMESLAVE,false);
- verify(statisticsManager).stopScheduling(nodeId);
- }
-
- /**
- * If getDeviceContext returns null nothing should happen
- */
- @Test
- public void gainVersionSafelyTest1() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(null);
- assertNull(lifecycleConductor.gainVersionSafely(nodeId));
- }
-
- /**
- * If getDeviceContext returns deviceContext getPrimaryConnectionContext() should be called
- */
- @Test
- public void gainVersionSafelyTest2() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(deviceContext);
- lifecycleConductor.gainVersionSafely(nodeId);
- verify(deviceContext,times(1)).getPrimaryConnectionContext();
+ when(deviceManager.gainContext(deviceInfo)).thenReturn(deviceContext);
+ when(deviceManager.onClusterRoleChange(deviceInfo, OfpRole.BECOMESLAVE)).thenReturn(listenableFuture);
+ lifecycleConductor.roleChangeOnDevice(deviceInfo,true,OfpRole.BECOMESLAVE,false);
+ verify(statisticsManager).stopScheduling(Mockito.<DeviceInfo>any());
}
/**
*/
@Test
public void gainConnectionStateSafelyTest1() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(null);
- assertNull(lifecycleConductor.gainConnectionStateSafely(nodeId));
+ when(deviceManager.gainContext(deviceInfo)).thenReturn(null);
+ assertNull(lifecycleConductor.gainConnectionStateSafely(deviceInfo));
}
/**
*/
@Test
public void gainConnectionStateSafelyTest2() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(deviceContext);
- lifecycleConductor.gainConnectionStateSafely(nodeId);
+ lifecycleConductor.gainConnectionStateSafely(deviceInfo);
verify(deviceContext,times(1)).getPrimaryConnectionContext();
}
*/
@Test
public void reserveXidForDeviceMessageTest1() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(null);
- assertNull(lifecycleConductor.reserveXidForDeviceMessage(nodeId));
+ when(deviceManager.gainContext(deviceInfo)).thenReturn(null);
+ assertNull(lifecycleConductor.reserveXidForDeviceMessage(deviceInfo));
}
/**
*/
@Test
public void reserveXidForDeviceMessageTest2() {
- when(deviceManager.getDeviceContextFromNodeId(nodeId)).thenReturn(deviceContext);
- lifecycleConductor.reserveXidForDeviceMessage(nodeId);
+ lifecycleConductor.reserveXidForDeviceMessage(deviceInfo);
verify(deviceContext,times(1)).reserveXidForDeviceMessage();
}
*/
@Test
public void deviceStartInitializationDoneTest() {
- lifecycleConductor.deviceStartInitializationDone(nodeId, false);
+ lifecycleConductor.deviceStartInitializationDone(deviceInfo, false);
verify(deviceContext,times(1)).shutdownConnection();
}
*/
@Test
public void deviceInitializationDoneTest() {
- lifecycleConductor.deviceInitializationDone(nodeId, false);
+ lifecycleConductor.deviceInitializationDone(deviceInfo, false);
verify(deviceContext,times(1)).shutdownConnection();
}
}
package org.opendaylight.openflowplugin.impl;
-import static org.mockito.Mockito.*;
-import static org.junit.Assert.*;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import org.opendaylight.controller.md.sal.binding.api.NotificationService;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.StatisticsManagerControlService;
private static final long RPC_REQUESTS_QUOTA = 500;
private static final long GLOBAL_NOTIFICATION_QUOTA = 131072;
+ private static final int THREAD_POOL_MIN_THREADS = 1;
+ private static final int THREAD_POOL_MAX_THREADS = 32000;
+ private static final long THREAD_POOL_TIMEOUT = 60;
private OpenFlowPluginProviderImpl provider;
when(rpcProviderRegistry.addRpcImplementation(eq(StatisticsManagerControlService.class), any())).thenReturn(controlServiceRegistration);
when(switchConnectionProvider.startup()).thenReturn(Futures.immediateCheckedFuture(null));
- provider = new OpenFlowPluginProviderImpl(RPC_REQUESTS_QUOTA, GLOBAL_NOTIFICATION_QUOTA);
+ provider = new OpenFlowPluginProviderImpl(
+ RPC_REQUESTS_QUOTA,
+ GLOBAL_NOTIFICATION_QUOTA,
+ THREAD_POOL_MIN_THREADS,
+ THREAD_POOL_MAX_THREADS,
+ THREAD_POOL_TIMEOUT);
+
provider.setDataBroker(dataBroker);
provider.setRpcProviderRegistry(rpcProviderRegistry);
provider.setNotificationProviderService(notificationService);
import com.google.common.util.concurrent.SettableFuture;
import java.math.BigInteger;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceConnectedHandler;
+import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInput;
*/
@Before
public void setUp() {
- connectionManagerImpl = new ConnectionManagerImpl(ECHO_REPLY_TIMEOUT);
+ final ThreadPoolLoggingExecutor threadPool = new ThreadPoolLoggingExecutor(0, Integer.MAX_VALUE,
+ 60L, TimeUnit.SECONDS,
+ new SynchronousQueue<>(), "ofppool");
+
+ connectionManagerImpl = new ConnectionManagerImpl(ECHO_REPLY_TIMEOUT, threadPool);
connectionManagerImpl.setDeviceConnectedHandler(deviceConnectedHandler);
final InetSocketAddress deviceAddress = InetSocketAddress.createUnresolved("yahoo", 42);
Mockito.when(connection.getRemoteAddress()).thenReturn(deviceAddress);
package org.opendaylight.openflowplugin.impl.connection;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import junit.framework.TestCase;
import org.junit.Test;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
public class OutboundQueueProviderImplTest extends TestCase {
private static final Long DUMMY_ENTRY_NUMBER = 44L;
connectionContextSpy = Mockito.spy(new ConnectionContextImpl(connectionAdapter));
Mockito.when(connectionContextSpy.getConnectionAdapter()).thenReturn(connectionAdapter);
Mockito.when(features.getDatapathId()).thenReturn(BigInteger.TEN);
+ Mockito.doNothing().when(connectionContextSpy).handshakeSuccessful();
handshakeListener = new HandshakeListenerImpl(connectionContextSpy, deviceConnectedHandler);
handshakeListener.setHandshakeContext(handshakeContext);
}
Mockito.verify(connectionContextSpy).changeStateToWorking();
Mockito.verify(connectionContextSpy).setFeatures(Matchers.any(FeaturesReply.class));
Mockito.verify(connectionContextSpy).setNodeId(nodeIdCaptor.capture());
+ Mockito.verify(connectionContextSpy).handshakeSuccessful();
Mockito.verify(deviceConnectedHandler).deviceConnected(connectionContextSpy);
Mockito.verify(handshakeContext).close();
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.SettableFuture;
import java.net.InetSocketAddress;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl;
+import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
Mockito.when(connectionContext.getConnectionAdapter()).thenReturn(connectionAdapter);
Mockito.when(connectionContext.getFeatures()).thenReturn(features);
- systemNotificationsListener = new SystemNotificationsListenerImpl(connectionContext, ECHO_REPLY_TIMEOUT);
+ final ThreadPoolLoggingExecutor threadPool = new ThreadPoolLoggingExecutor(0, Integer.MAX_VALUE,
+ 60L, TimeUnit.SECONDS,
+ new SynchronousQueue<>(), "opfpool");
+
+ systemNotificationsListener = new SystemNotificationsListenerImpl(connectionContext, ECHO_REPLY_TIMEOUT, threadPool);
}
@After
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicLong;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
-import org.mockito.stubbing.Answer;
import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
-import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
-import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.Error;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
private static final BigInteger DUMMY_DATAPATH_ID = new BigInteger("55");
Xid xid;
Xid xidMulti;
- DeviceContextImpl deviceContext;
+
+ DeviceContext deviceContext;
@Mock
TransactionChainManager txChainManager;
@Mock
RequestContext<GetAsyncReply> requestContext;
@Mock
RequestContext<MultipartReply> requestContextMultiReply;
-
@Mock
ConnectionContext connectionContext;
@Mock
private MessageTranslator<Object, Object> messageTranslatorFlowRemoved;
@Mock
private LifecycleConductor lifecycleConductor;
+ @Mock
+ private DeviceInfo deviceInfo;
private InOrder inOrderDevState;
private DeviceContext deviceContextSpy;
@Before
- public void setUp() {
+ public void setUp() throws Exception{
final CheckedFuture<Optional<Node>, ReadFailedException> noExistNodeFuture = Futures.immediateCheckedFuture(Optional.<Node>absent());
Mockito.when(rTx.read(LogicalDatastoreType.OPERATIONAL, nodeKeyIdent)).thenReturn(noExistNodeFuture);
Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
Mockito.when(dataBroker.createTransactionChain(Mockito.any(TransactionChainManager.class))).thenReturn(txChainFactory);
- Mockito.when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodeKeyIdent);
- Mockito.when(deviceState.getNodeId()).thenReturn(nodeId);
-// txChainManager = new TransactionChainManager(dataBroker, deviceState);
+ Mockito.when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(nodeKeyIdent);
+ Mockito.when(deviceInfo.getNodeId()).thenReturn(nodeId);
+ Mockito.when(deviceInfo.getDatapathId()).thenReturn(BigInteger.ONE);
final SettableFuture<RpcResult<GetAsyncReply>> settableFuture = SettableFuture.create();
final SettableFuture<RpcResult<MultipartReply>> settableFutureMultiReply = SettableFuture.create();
Mockito.when(requestContext.getFuture()).thenReturn(settableFuture);
- Mockito.doAnswer(new Answer<Object>() {
- @SuppressWarnings("unchecked")
- @Override
- public Object answer(final InvocationOnMock invocation) {
- settableFuture.set((RpcResult<GetAsyncReply>) invocation.getArguments()[0]);
- return null;
- }
+ Mockito.doAnswer(invocation -> {
+ settableFuture.set((RpcResult<GetAsyncReply>) invocation.getArguments()[0]);
+ return null;
}).when(requestContext).setResult(any(RpcResult.class));
Mockito.when(requestContextMultiReply.getFuture()).thenReturn(settableFutureMultiReply);
- Mockito.doAnswer(new Answer<Object>() {
- @SuppressWarnings("unchecked")
- @Override
- public Object answer(final InvocationOnMock invocation) {
- settableFutureMultiReply.set((RpcResult<MultipartReply>) invocation.getArguments()[0]);
- return null;
- }
+ Mockito.doAnswer(invocation -> {
+ settableFutureMultiReply.set((RpcResult<MultipartReply>) invocation.getArguments()[0]);
+ return null;
}).when(requestContextMultiReply).setResult(any(RpcResult.class));
Mockito.when(txChainFactory.newWriteOnlyTransaction()).thenReturn(wTx);
Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
Mockito.when(connectionContext.getOutboundQueueProvider()).thenReturn(outboundQueueProvider);
Mockito.when(connectionContext.getConnectionAdapter()).thenReturn(connectionAdapter);
+ Mockito.when(connectionContext.getDeviceInfo()).thenReturn(deviceInfo);
final FeaturesReply mockedFeaturesReply = mock(FeaturesReply.class);
when(connectionContext.getFeatures()).thenReturn(mockedFeaturesReply);
when(connectionContext.getFeatures().getCapabilities()).thenReturn(mock(Capabilities.class));
- Mockito.when(deviceState.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+ Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
Mockito.when(featuresOutput.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
Mockito.when(featuresOutput.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
- Mockito.when(deviceState.getFeatures()).thenReturn(featuresOutput);
- Mockito.when(messageTranslatorPacketReceived.translate(any(Object.class), any(DeviceState.class), any(Object.class))).thenReturn(mock(PacketReceived.class));
- Mockito.when(messageTranslatorFlowCapableNodeConnector.translate(any(Object.class), any(DeviceState.class), any(Object.class))).thenReturn(mock(FlowCapableNodeConnector.class));
+ Mockito.when(messageTranslatorPacketReceived.translate(any(Object.class), any(DeviceInfo.class), any(Object.class))).thenReturn(mock(PacketReceived.class));
+ Mockito.when(messageTranslatorFlowCapableNodeConnector.translate(any(Object.class), any(DeviceInfo.class), any(Object.class))).thenReturn(mock(FlowCapableNodeConnector.class));
Mockito.when(translatorLibrary.lookupTranslator(eq(new TranslatorKey(OFConstants.OFP_VERSION_1_3, PacketIn.class.getName())))).thenReturn(messageTranslatorPacketReceived);
Mockito.when(translatorLibrary.lookupTranslator(eq(new TranslatorKey(OFConstants.OFP_VERSION_1_3, PortGrouping.class.getName())))).thenReturn(messageTranslatorFlowCapableNodeConnector);
Mockito.when(translatorLibrary.lookupTranslator(eq(new TranslatorKey(OFConstants.OFP_VERSION_1_3,
.thenReturn(messageTranslatorFlowRemoved);
Mockito.when(lifecycleConductor.getMessageIntelligenceAgency()).thenReturn(messageIntelligenceAgency);
- deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, lifecycleConductor, outboundQueueProvider, translatorLibrary, false);
-
+ deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, lifecycleConductor, outboundQueueProvider, translatorLibrary);
deviceContextSpy = Mockito.spy(deviceContext);
xid = new Xid(atomicLong.incrementAndGet());
xidMulti = new Xid(atomicLong.incrementAndGet());
+
+ Mockito.doNothing().when(deviceContextSpy).writeToTransaction(Mockito.<LogicalDatastoreType>any(), Mockito.<InstanceIdentifier>any(), any());
}
@Test(expected = NullPointerException.class)
public void testDeviceContextImplConstructorNullDataBroker() throws Exception {
- new DeviceContextImpl(connectionContext, deviceState, null, lifecycleConductor, outboundQueueProvider, translatorLibrary, false).close();
+ new DeviceContextImpl(connectionContext, deviceState, null, lifecycleConductor, outboundQueueProvider, translatorLibrary).close();
}
@Test(expected = NullPointerException.class)
public void testDeviceContextImplConstructorNullDeviceState() throws Exception {
- new DeviceContextImpl(connectionContext, null, dataBroker, lifecycleConductor, outboundQueueProvider, translatorLibrary, false).close();
+ new DeviceContextImpl(connectionContext, null, dataBroker, lifecycleConductor, outboundQueueProvider, translatorLibrary).close();
}
@Test(expected = NullPointerException.class)
public void testDeviceContextImplConstructorNullTimer() throws Exception {
- new DeviceContextImpl(null, deviceState, dataBroker, lifecycleConductor, outboundQueueProvider, translatorLibrary, false).close();
+ new DeviceContextImpl(null, deviceState, dataBroker, lifecycleConductor, outboundQueueProvider, translatorLibrary).close();
}
@Test
public void testInitialSubmitTransaction() throws Exception {
Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
final InstanceIdentifier<Nodes> dummyII = InstanceIdentifier.create(Nodes.class);
- deviceContext.getTransactionChainManager().activateTransactionManager() ;
- deviceContext.getTransactionChainManager().enableSubmit();
+ ((DeviceContextImpl) deviceContext).getTransactionChainManager().activateTransactionManager() ;
+ ((DeviceContextImpl) deviceContext).getTransactionChainManager().enableSubmit();
deviceContext.addDeleteToTxChain(LogicalDatastoreType.CONFIGURATION, dummyII);
- deviceContext.initialSubmitTransaction();
+ ((DeviceContextImpl) deviceContext).initialSubmitTransaction();
verify(wTx).submit();
}
@Test
public void testAddDeleteToTxChain() throws Exception{
final InstanceIdentifier<Nodes> dummyII = InstanceIdentifier.create(Nodes.class);
- deviceContext.getTransactionChainManager().activateTransactionManager() ;
- deviceContext.getTransactionChainManager().enableSubmit();
+ ((DeviceContextImpl) deviceContext).getTransactionChainManager().activateTransactionManager() ;
+ ((DeviceContextImpl) deviceContext).getTransactionChainManager().enableSubmit();
deviceContext.addDeleteToTxChain(LogicalDatastoreType.CONFIGURATION, dummyII);
verify(wTx).delete(eq(LogicalDatastoreType.CONFIGURATION), eq(dummyII));
}
*/
@Test
public void testSubmitTransaction() throws Exception {
- deviceContext.getTransactionChainManager().activateTransactionManager() ;
- deviceContext.getTransactionChainManager().enableSubmit();
+ ((DeviceContextImpl) deviceContext).getTransactionChainManager().activateTransactionManager() ;
+ ((DeviceContextImpl) deviceContext).getTransactionChainManager().enableSubmit();
assertTrue(deviceContext.submitTransaction());
}
assertNotNull(deviceMeterRegistry);
}
- @Test
- public void testGetRpcContext() {
- final RpcContext rpcContext = mock(RpcContext.class);
- deviceContext.setRpcContext(rpcContext);
- assertNotNull(deviceContext.getRpcContext());
- }
-
@Test
public void testProcessReply() {
final Error mockedError = mock(Error.class);
when(connectionContext.getConnectionAdapter()).thenReturn(mockedConnectionAdapter);
final NodeId dummyNodeId = new NodeId("dummyNodeId");
- when(deviceState.getNodeId()).thenReturn(dummyNodeId);
+ when(deviceInfo.getNodeId()).thenReturn(dummyNodeId);
final ConnectionContext mockedAuxiliaryConnectionContext = prepareConnectionContext();
deviceContext.addAuxiliaryConnectionContext(mockedAuxiliaryConnectionContext);
assertEquals(messageIntelligenceAgency, pickedMessageSpy);
}
- @Test
- public void testNodeConnector() {
- final NodeConnectorRef mockedNodeConnectorRef = mock(NodeConnectorRef.class);
- deviceContext.storeNodeConnectorRef(DUMMY_PORT_NUMBER, mockedNodeConnectorRef);
- final NodeConnectorRef nodeConnectorRef = deviceContext.lookupNodeConnectorRef(DUMMY_PORT_NUMBER);
- assertEquals(mockedNodeConnectorRef, nodeConnectorRef);
-
- }
-
@Test
public void testOnPublished() {
final ConnectionContext auxiliaryConnectionContext = addDummyAuxiliaryConnectionContext();
}
@Test
- public void testPortStatusMessage() {
+ public void testPortStatusMessage() throws Exception{
final PortStatusMessage mockedPortStatusMessage = mock(PortStatusMessage.class);
final Class dummyClass = Class.class;
when(mockedPortStatusMessage.getImplementedInterface()).thenReturn(dummyClass);
final GetFeaturesOutput mockedFeature = mock(GetFeaturesOutput.class);
when(mockedFeature.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
- when(deviceState.getFeatures()).thenReturn(mockedFeature);
when(mockedPortStatusMessage.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
when(mockedPortStatusMessage.getReason()).thenReturn(PortReason.OFPPRADD);
+ when(mockedPortStatusMessage.getPortNo()).thenReturn(42L);
OpenflowPortsUtil.init();
- deviceContext.processPortStatusMessage(mockedPortStatusMessage);
-// verify(txChainManager).writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class), any(DataObject.class));
+ deviceContextSpy.processPortStatusMessage(mockedPortStatusMessage);
+ verify(deviceContextSpy).writeToTransaction(Mockito.<LogicalDatastoreType>any(), Mockito.<InstanceIdentifier>any(), any());
+ verify(deviceContextSpy).submitTransaction();
}
@Test
.setPriority(42)
.setCookie(new FlowCookie(BigInteger.ONE))
.setMatch(new MatchBuilder().build());
+ final NotificationPublishService mockedNotificationPublishService = mock(NotificationPublishService.class);
- Mockito.when(messageTranslatorFlowRemoved.translate(any(Object.class), any(DeviceState.class), any(Object.class)))
+ Mockito.when(messageTranslatorFlowRemoved.translate(any(Object.class), any(DeviceInfo.class), any(Object.class)))
.thenReturn(flowRemovedMdsalBld.build());
// insert flow+flowId into local registry
.child(Table.class, new TableKey((short) 0))
.child(Flow.class, new FlowKey(new FlowId("ut-ofp:f456")));
+ deviceContext.setNotificationPublishService(mockedNotificationPublishService);
deviceContext.processFlowRemovedMessage(flowRemovedBld.build());
Mockito.verify(itemLifecycleListener).onRemoved(flowToBeRemovedPath);
}
final NotificationPublishService mockedNotificationPublishService = mock(NotificationPublishService.class);
deviceContext.setNotificationPublishService(mockedNotificationPublishService);
- deviceContext.setExtensionConverterProvider(mockedExtensionConverterProvider);
+ ((DeviceContextImpl) deviceContext).setExtensionConverterProvider(mockedExtensionConverterProvider);
deviceContext.processExperimenterMessage(experimenterMessage);
verify(mockedNotificationPublishService).offerNotification(any(ExperimenterMessageFromDev.class));
assertEquals(0, deviceContext.getDeviceMeterRegistry().getAllMeterIds().size());
}
-
- @Test
- public void testOnClusterRoleChange() throws Exception {
- // test role.equals(oldRole)
- Assert.assertNull(deviceContextSpy.onClusterRoleChange(OfpRole.BECOMEMASTER, OfpRole.BECOMEMASTER).get());
-
- // test call transactionChainManager.deactivateTransactionManager()
- Assert.assertNull(deviceContextSpy.onClusterRoleChange(OfpRole.BECOMESLAVE, OfpRole.NOCHANGE).get());
-
- // test call MdSalRegistrationUtils.unregisterServices(rpcContext)
- final RpcContext rpcContext = mock(RpcContext.class);
- deviceContextSpy.setRpcContext(rpcContext);
- Assert.assertNull(deviceContextSpy.onClusterRoleChange(OfpRole.BECOMESLAVE, OfpRole.NOCHANGE).get());
-
- final StatisticsContext statisticsContext = mock(StatisticsContext.class);
- deviceContextSpy.setStatisticsContext(statisticsContext);
-
- deviceContextSpy.onClusterRoleChange(OfpRole.NOCHANGE, OfpRole.BECOMEMASTER);
- verify(deviceContextSpy).onDeviceTakeClusterLeadership();
-
- Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
- deviceContextSpy.onClusterRoleChange(OfpRole.NOCHANGE, OfpRole.BECOMESLAVE);
- verify(deviceContextSpy).onDeviceLostClusterLeadership();
- }
}
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import io.netty.util.TimerTask;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
-
-import com.google.common.util.concurrent.Futures;
-import io.netty.util.TimerTask;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.features.reply.PhyPortBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
@RunWith(MockitoJUnitRunner.class)
public class DeviceManagerImplTest {
private static final long TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA = 2000l;
private static final int barrierCountLimit = 25600;
private static final int barrierIntervalNanos = 500;
+ public static final NodeId DUMMY_NODE_ID = new NodeId("dummyNodeId");
@Mock
CheckedFuture<Void, TransactionCommitFailedException> mockedFuture;
private LifecycleConductor lifecycleConductor;
@Mock
private MessageIntelligenceAgency messageIntelligenceAgency;
+ @Mock
+ private DeviceInfo deviceInfo;
@Before
public void setUp() throws Exception {
OpenflowPortsUtil.init();
- when(mockConnectionContext.getNodeId()).thenReturn(new NodeId("dummyNodeId"));
+ when(mockConnectionContext.getNodeId()).thenReturn(DUMMY_NODE_ID);
when(mockConnectionContext.getFeatures()).thenReturn(mockFeatures);
when(mockConnectionContext.getConnectionAdapter()).thenReturn(mockedConnectionAdapter);
+ when(mockConnectionContext.getDeviceInfo()).thenReturn(deviceInfo);
when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockConnectionContext);
+ when(deviceInfo.getNodeId()).thenReturn(DUMMY_NODE_ID);
final Capabilities capabilitiesV13 = mock(Capabilities.class);
final CapabilitiesV10 capabilitiesV10 = mock(CapabilitiesV10.class);
final DeviceManagerImpl deviceManager = prepareDeviceManager(withException);
final DeviceState mockedDeviceState = mock(DeviceState.class);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
- when(mockedDeviceState.getNodeId()).thenReturn(mockedNodeId);
if (withException) {
doThrow(new IllegalStateException("dummy")).when(mockedDeviceContext).initialSubmitTransaction();
}
- deviceManager.addDeviceContextToMap(mockedNodeId, mockedDeviceContext);
- deviceManager.onDeviceContextLevelUp(mockedDeviceContext.getDeviceState().getNodeId());
+ deviceManager.addDeviceContextToMap(deviceInfo, mockedDeviceContext);
+ deviceManager.onDeviceContextLevelUp(deviceInfo);
if (withException) {
verify(mockedDeviceContext).close();
} else {
deviceManager.deviceConnected(mockConnectionContext);
final InOrder order = inOrder(mockConnectionContext);
- order.verify(mockConnectionContext).getFeatures();
order.verify(mockConnectionContext).setOutboundQueueProvider(any(OutboundQueueProvider.class));
order.verify(mockConnectionContext).setOutboundQueueHandleRegistration(
Mockito.<OutboundQueueHandlerRegistration<OutboundQueueProvider>>any());
- order.verify(mockConnectionContext).getNodeId();
- verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<NodeId>any());
+ verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<DeviceInfo>any());
}
@Test
.setPortNo(41L);
when(mockFeatures.getPhyPort()).thenReturn(Collections.singletonList(phyPort.build()));
final MessageTranslator<Object, Object> mockedTranslator = mock(MessageTranslator.class);
- when(mockedTranslator.translate(Matchers.<Object>any(), Matchers.<DeviceState>any(), Matchers.any()))
+ when(mockedTranslator.translate(Matchers.<Object>any(), Matchers.<DeviceInfo>any(), Matchers.any()))
.thenReturn(null);
when(translatorLibrary.lookupTranslator(Matchers.<TranslatorKey>any())).thenReturn(mockedTranslator);
deviceManager.deviceConnected(mockConnectionContext);
final InOrder order = inOrder(mockConnectionContext);
- order.verify(mockConnectionContext).getFeatures();
order.verify(mockConnectionContext).setOutboundQueueProvider(any(OutboundQueueProvider.class));
order.verify(mockConnectionContext).setOutboundQueueHandleRegistration(
Mockito.<OutboundQueueHandlerRegistration<OutboundQueueProvider>>any());
- order.verify(mockConnectionContext).getNodeId();
- verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<NodeId>any());
+ verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<DeviceInfo>any());
}
@Test
when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
when(deviceContext.getDeviceState()).thenReturn(deviceState);
- final ConcurrentHashMap<NodeId, DeviceContext> deviceContexts = getContextsCollection(deviceManager);
- deviceContexts.put(mockedNodeId, deviceContext);
+ final ConcurrentHashMap<DeviceInfo, DeviceContext> deviceContexts = getContextsCollection(deviceManager);
+ deviceContexts.put(deviceInfo, deviceContext);
deviceManager.onDeviceDisconnected(connectionContext);
public void testClose() throws Exception {
final DeviceContext deviceContext = mock(DeviceContext.class);
final DeviceManagerImpl deviceManager = prepareDeviceManager();
- final ConcurrentHashMap<NodeId, DeviceContext> deviceContexts = getContextsCollection(deviceManager);
- deviceContexts.put(mockedNodeId, deviceContext);
+ final ConcurrentHashMap<DeviceInfo, DeviceContext> deviceContexts = getContextsCollection(deviceManager);
+ deviceContexts.put(deviceInfo, deviceContext);
Assert.assertEquals(1, deviceContexts.size());
deviceManager.close();
verify(deviceContext, Mockito.never()).close();
}
- private static ConcurrentHashMap<NodeId, DeviceContext> getContextsCollection(final DeviceManagerImpl deviceManager) throws NoSuchFieldException, IllegalAccessException {
+ private static ConcurrentHashMap<DeviceInfo, DeviceContext> getContextsCollection(final DeviceManagerImpl deviceManager) throws NoSuchFieldException, IllegalAccessException {
// HACK: contexts collection for testing shall be accessed in some more civilized way
final Field contextsField = DeviceManagerImpl.class.getDeclaredField("deviceContexts");
Assert.assertNotNull(contextsField);
contextsField.setAccessible(true);
- return (ConcurrentHashMap<NodeId, DeviceContext>) contextsField.get(deviceManager);
+ return (ConcurrentHashMap<DeviceInfo, DeviceContext>) contextsField.get(deviceManager);
}
}
package org.opendaylight.openflowplugin.impl.device;
-import java.util.Arrays;
-import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.features.reply.PhyPort;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.features.reply.PhyPortBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
/**
* openflowplugin-impl
* org.opendaylight.openflowplugin.impl.device
*
* test of {@link DeviceStateImpl} - lightweight version, using basic ways (TDD)
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *
- * Created: Mar 29, 2015
*/
@RunWith(MockitoJUnitRunner.class)
public class DeviceStateImplTest {
- private NodeId nodeId;
@Mock
- private FeaturesReply featuresReply;
- private DeviceStateImpl deviceState;
+ private DeviceInfo deviceInfo;
- private final short version = 13;
- private final long portNr = 10L;
- private final Long portBandwidth = 1024L;
- private final List<PhyPort> pPort = Arrays.asList(new PhyPortBuilder()
- .setPortNo(portNr).setMaxSpeed(portBandwidth).build());
+ private DeviceStateImpl deviceState;
@Before
public void initialization() {
- nodeId = new NodeId("test-node-id");
- Mockito.when(featuresReply.getVersion()).thenReturn(version);
- Mockito.when(featuresReply.getPhyPort()).thenReturn(pPort);
- deviceState = new DeviceStateImpl(featuresReply, nodeId);
- }
-
- /**
- * Test method for {@link DeviceStateImpl#DeviceStateImpl(FeaturesReply, NodeId)}.
- */
- @Test(expected=NullPointerException.class)
- public void testDeviceStateImplNullNodeId(){
- new DeviceStateImpl(featuresReply, null);
- }
-
- /**
- * Test method for {@link DeviceStateImpl#DeviceStateImpl(FeaturesReply, NodeId)}.
- */
- @Test(expected=IllegalArgumentException.class)
- public void testDeviceStateImplNullFeaturesReply(){
- new DeviceStateImpl(null, nodeId);
- }
-
- /**
- * Test method for {@link DeviceStateImpl#getNodeId()}.
- */
- @Test
- public void testGetNodeId(){
- final NodeId getNodeId = deviceState.getNodeId();
- Assert.assertNotNull(getNodeId);
- Assert.assertEquals(nodeId, getNodeId);
- }
-
- /**
- * Test method for {@link DeviceStateImpl#getFeatures()}.
- */
- @Test
- public void testGetFeatures(){
- final GetFeaturesOutputBuilder expetedResult = new GetFeaturesOutputBuilder(featuresReply);
- final GetFeaturesOutput getFeatures = deviceState.getFeatures();
- Assert.assertNotNull(getFeatures);
- Assert.assertEquals(expetedResult.getVersion(), getFeatures.getVersion());
- Assert.assertEquals(expetedResult.getPhyPort(), getFeatures.getPhyPort());
+ deviceState = new DeviceStateImpl(deviceInfo);
}
@Test
import io.netty.util.HashedWheelTimer;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
@Mock
DeviceState deviceState;
@Mock
+ DeviceInfo deviceInfo;
+ @Mock
LifecycleConductor conductor;
@Mock
.thenReturn(txChain);
nodeId = new NodeId("h2g2:42");
nodeKeyIdent = DeviceStateUtil.createNodeInstanceIdentifier(nodeId);
- Mockito.when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodeKeyIdent);
- Mockito.when(deviceState.getNodeId()).thenReturn(nodeId);
- txChainManager = new TransactionChainManager(dataBroker, deviceState, conductor);
+ Mockito.when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(nodeKeyIdent);
+ Mockito.when(deviceInfo.getNodeId()).thenReturn(nodeId);
+ txChainManager = new TransactionChainManager(dataBroker, deviceInfo, conductor);
Mockito.when(txChain.newWriteOnlyTransaction()).thenReturn(writeTx);
path = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(nodeId));
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
private DeviceContext deviceContext;
@Mock
private DeviceState deviceState;
+ @Mock
+ private DeviceInfo deviceInfo;
@Before
}
FLOWS_STATISTICS_UPDATE_BUILDER.setFlowAndStatisticsMapList(flowAndStatisticsMapListList);
Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
- Mockito.when(deviceState.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+ Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
}
@Test
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
@Mock
private LifecycleConductor conductor;
+ @Mock
+ private DeviceInfo deviceInfo;
+
private final NodeId nodeId = NodeId.getDefaultInstance("openflow:1");
private final Entity entity = new Entity(RoleManager.ENTITY_TYPE, nodeId.getValue());
private final Entity txEntity = new Entity(RoleManager.TX_ENTITY_TYPE, nodeId.getValue());
@Before
public void setup() throws CandidateAlreadyRegisteredException {
- roleContext = new RoleContextImpl(nodeId, entityOwnershipService, entity, txEntity, conductor);
+ roleContext = new RoleContextImpl(deviceInfo, entityOwnershipService, entity, txEntity, conductor);
Mockito.when(entityOwnershipService.registerCandidate(entity)).thenReturn(entityOwnershipCandidateRegistration);
Mockito.when(entityOwnershipService.registerCandidate(txEntity)).thenReturn(entityOwnershipCandidateRegistration);
+ Mockito.when(deviceInfo.getNodeId()).thenReturn(nodeId);
}
//@Test
@Test
public void testCreateRequestContext() throws Exception {
roleContext.createRequestContext();
- Mockito.verify(conductor).reserveXidForDeviceMessage(nodeId);
+ Mockito.verify(conductor).reserveXidForDeviceMessage(deviceInfo);
}
@Test(expected = NullPointerException.class)
@Test
public void testGetNodeId() throws Exception {
- Assert.assertTrue(roleContext.getNodeId().equals(nodeId));
+ Assert.assertTrue(roleContext.getDeviceInfo().getNodeId().equals(nodeId));
}
@Test
package org.opendaylight.openflowplugin.impl.role;
-import java.math.BigInteger;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import com.google.common.base.VerifyException;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-
@RunWith(MockitoJUnitRunner.class)
public class RoleManagerImplTest {
@Mock
DeviceState deviceState;
+ @Mock
+ DeviceInfo deviceInfo;
+
+ @Mock
+ DeviceInfo deviceInfo2;
+
+ @Mock
+ MessageSpy messageSpy;
+
+ @Mock
+ OutboundQueue outboundQueue;
+
@Mock
GetFeaturesOutput featuresOutput;
private RoleManagerImpl roleManagerSpy;
private RoleContext roleContextSpy;
private final NodeId nodeId = NodeId.getDefaultInstance("openflow:1");
+ private final NodeId nodeId2 = NodeId.getDefaultInstance("openflow:2");
- private final EntityOwnershipChange masterEntity = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), false, true, true);
- private final EntityOwnershipChange masterTxEntity = new EntityOwnershipChange(RoleManagerImpl.makeTxEntity(nodeId), false, true, true);
- private final EntityOwnershipChange slaveEntity = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), true, false, true);
- private final EntityOwnershipChange slaveTxEntityLast = new EntityOwnershipChange(RoleManagerImpl.makeTxEntity(nodeId), true, false, false);
- private final EntityOwnershipChange masterEntityNotOwner = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), true, false, true);
+
+ private final EntityOwnershipChange masterEntity = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), false, true, true, false);
+ private final EntityOwnershipChange masterTxEntity = new EntityOwnershipChange(RoleManagerImpl.makeTxEntity(nodeId), false, true, true, false);
+ private final EntityOwnershipChange slaveEntity = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), true, false, true, false);
+ private final EntityOwnershipChange slaveTxEntityLast = new EntityOwnershipChange(RoleManagerImpl.makeTxEntity(nodeId), true, false, false, false);
+ private final EntityOwnershipChange masterEntityNotOwner = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), true, false, true, false);
private InOrder inOrder;
@Before
public void setUp() throws Exception {
CheckedFuture<Void, TransactionCommitFailedException> future = Futures.immediateCheckedFuture(null);
- Mockito.when(deviceState.getFeatures()).thenReturn(featuresOutput);
Mockito.when(entityOwnershipService.registerListener(Mockito.anyString(), Mockito.any(EntityOwnershipListener.class))).thenReturn(entityOwnershipListenerRegistration);
Mockito.when(entityOwnershipService.registerCandidate(Mockito.any(Entity.class))).thenReturn(entityOwnershipCandidateRegistration);
Mockito.when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
+ Mockito.when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
+ Mockito.when(deviceContext.getMessageSpy()).thenReturn(messageSpy);
+ Mockito.when(deviceContext.getPrimaryConnectionContext().getOutboundQueueProvider()).thenReturn(outboundQueue);
Mockito.when(connectionContext.getFeatures()).thenReturn(featuresReply);
Mockito.when(connectionContext.getNodeId()).thenReturn(nodeId);
Mockito.when(connectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
- Mockito.when(featuresReply.getDatapathId()).thenReturn(new BigInteger("1"));
- Mockito.when(featuresReply.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
- Mockito.doNothing().when(deviceInitializationPhaseHandler).onDeviceContextLevelUp(Mockito.<NodeId>any());
- Mockito.doNothing().when(deviceTerminationPhaseHandler).onDeviceContextLevelDown(Mockito.<DeviceContext>any());
+ Mockito.when(deviceInfo.getDatapathId()).thenReturn(new BigInteger("1"));
+ Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+ Mockito.when(deviceInfo.getNodeId()).thenReturn(nodeId);
+ Mockito.doNothing().when(deviceInitializationPhaseHandler).onDeviceContextLevelUp(Mockito.<DeviceInfo>any());
+ Mockito.doNothing().when(deviceTerminationPhaseHandler).onDeviceContextLevelDown(Mockito.<DeviceInfo>any());
Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(writeTransaction);
Mockito.when(writeTransaction.submit()).thenReturn(future);
- Mockito.when(deviceManager.getDeviceContextFromNodeId(Mockito.<NodeId>any())).thenReturn(deviceContext);
+ Mockito.when(deviceInfo.getNodeId()).thenReturn(nodeId);
+ Mockito.when(deviceInfo2.getNodeId()).thenReturn(nodeId2);
+ Mockito.when(deviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
roleManager = new RoleManagerImpl(entityOwnershipService, dataBroker, conductor);
roleManager.setDeviceInitializationPhaseHandler(deviceInitializationPhaseHandler);
roleManager.setDeviceTerminationPhaseHandler(deviceTerminationPhaseHandler);
- Mockito.when(conductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(deviceContext);
+ Mockito.when(conductor.getDeviceContext(deviceInfo)).thenReturn(deviceContext);
roleManagerSpy = Mockito.spy(roleManager);
- roleManagerSpy.onDeviceContextLevelUp(nodeId);
- roleContextSpy = Mockito.spy(roleManager.getRoleContext(nodeId));
+ roleManagerSpy.onDeviceContextLevelUp(deviceInfo);
+ Mockito.doNothing().when(roleManagerSpy).makeDeviceRoleChange(Mockito.<OfpRole>any(), Mockito.<RoleContext>any(), Mockito.anyBoolean());
+ roleContextSpy = Mockito.spy(roleManager.getRoleContext(deviceInfo));
+ Mockito.when(roleContextSpy.getDeviceInfo()).thenReturn(deviceInfo);
+ Mockito.when(roleContextSpy.getDeviceInfo().getNodeId()).thenReturn(nodeId);
inOrder = Mockito.inOrder(entityOwnershipListenerRegistration, roleManagerSpy, roleContextSpy);
}
@Test(expected = VerifyException.class)
public void testOnDeviceContextLevelUp() throws Exception {
- roleManagerSpy.onDeviceContextLevelUp(nodeId);
- inOrder.verify(roleManagerSpy).onDeviceContextLevelUp(nodeId);
+ roleManagerSpy.onDeviceContextLevelUp(deviceInfo);
+ inOrder.verify(roleManagerSpy).onDeviceContextLevelUp(deviceInfo);
inOrder.verifyNoMoreInteractions();
}
roleManagerSpy.ownershipChanged(masterTxEntity);
roleManagerSpy.close();
inOrder.verify(entityOwnershipListenerRegistration, Mockito.calls(2)).close();
- inOrder.verify(roleManagerSpy).removeDeviceFromOperationalDS(nodeId);
+ inOrder.verify(roleManagerSpy).removeDeviceFromOperationalDS(Mockito.eq(deviceInfo), Mockito.anyInt());
inOrder.verifyNoMoreInteractions();
}
roleManagerSpy.ownershipChanged(slaveEntity);
roleManagerSpy.close();
inOrder.verify(entityOwnershipListenerRegistration, Mockito.calls(2)).close();
- inOrder.verify(roleManagerSpy, Mockito.never()).removeDeviceFromOperationalDS(nodeId);
+ inOrder.verify(roleManagerSpy, Mockito.never()).removeDeviceFromOperationalDS(Mockito.eq(deviceInfo), Mockito.anyInt());
inOrder.verifyNoMoreInteractions();
}
@Test
public void testOnDeviceContextLevelDown() throws Exception {
- roleManagerSpy.onDeviceContextLevelDown(deviceContext);
- inOrder.verify(roleManagerSpy).onDeviceContextLevelDown(deviceContext);
+ roleManagerSpy.onDeviceContextLevelDown(deviceInfo);
+ inOrder.verify(roleManagerSpy).onDeviceContextLevelDown(deviceInfo);
inOrder.verifyNoMoreInteractions();
}
inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isTxCandidateRegistered();
inOrder.verify(roleContextSpy, Mockito.calls(1)).unregisterCandidate(Mockito.<Entity>any());
inOrder.verify(roleContextSpy, Mockito.never()).close();
- inOrder.verify(roleManagerSpy, Mockito.calls(1)).removeDeviceFromOperationalDS(Mockito.<NodeId>any());
+ inOrder.verify(roleManagerSpy, Mockito.calls(1)).removeDeviceFromOperationalDS(Mockito.any(), Mockito.anyInt());
}
@Test
Mockito.when(roleContextSpy.isTxCandidateRegistered()).thenReturn(false);
roleManagerSpy.changeOwnershipForTxEntity(slaveTxEntityLast, roleContextSpy);
verify(roleContextSpy).close();
- verify(roleContextSpy).getNodeId();
- verify(conductor).closeConnection(nodeId);
+ verify(conductor).closeConnection(deviceInfo);
}
@Test
Mockito.when(roleContextSpy.isTxCandidateRegistered()).thenReturn(true);
roleManagerSpy.changeOwnershipForTxEntity(masterEntityNotOwner, roleContextSpy);
verify(roleContextSpy).close();
- verify(conductor).closeConnection(nodeId);
+ verify(conductor).closeConnection(deviceInfo);
}
@Test
public void testAddListener() throws Exception {
roleManager.addRoleChangeListener((new RoleChangeListener() {
@Override
- public void roleInitializationDone(final NodeId nodeId, final boolean success) {
- Assert.assertTrue(nodeId.equals(nodeId));
+ public void roleInitializationDone(final DeviceInfo deviceInfo_, final boolean success) {
+ Assert.assertTrue(deviceInfo.equals(deviceInfo_));
Assert.assertTrue(success);
}
@Override
- public void roleChangeOnDevice(final NodeId nodeId_, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
- Assert.assertTrue(nodeId.equals(nodeId_));
+ public void roleChangeOnDevice(final DeviceInfo deviceInfo_, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
+ Assert.assertTrue(RoleManagerImplTest.this.deviceInfo.equals(deviceInfo_));
Assert.assertTrue(success);
Assert.assertFalse(initializationPhase);
Assert.assertTrue(newRole.equals(OfpRole.BECOMEMASTER));
}
}));
- roleManager.notifyListenersRoleInitializationDone(nodeId, true);
- roleManager.notifyListenersRoleChangeOnDevice(nodeId, true, OfpRole.BECOMEMASTER, false);
- }
-
- @Test
- public void testMakeDeviceRoleChange() throws Exception{
- roleManagerSpy.makeDeviceRoleChange(OfpRole.BECOMEMASTER, roleContextSpy, true);
- verify(roleManagerSpy, atLeastOnce()).sendRoleChangeToDevice(Mockito.<OfpRole>any(), Mockito.<RoleContext>any());
- verify(roleManagerSpy, atLeastOnce()).notifyListenersRoleChangeOnDevice(Mockito.<NodeId>any(), eq(true), Mockito.<OfpRole>any(), eq(true));
+ roleManager.notifyListenersRoleInitializationDone(deviceInfo, true);
+ roleManager.notifyListenersRoleChangeOnDevice(deviceInfo, true, OfpRole.BECOMEMASTER, false);
}
@Test
public void testServicesChangeDone() throws Exception {
- final NodeId nodeId2 = NodeId.getDefaultInstance("openflow:2");
- roleManagerSpy.setRoleContext(nodeId2, roleContextSpy);
- roleManagerSpy.servicesChangeDone(nodeId2, true);
+ roleManagerSpy.setRoleContext(deviceInfo2, roleContextSpy);
+ roleManagerSpy.servicesChangeDone(deviceInfo2, true);
verify(roleContextSpy).unregisterCandidate(Mockito.<Entity>any());
}
@Test
public void testServicesChangeDoneContextIsNull() throws Exception {
- final NodeId nodeId2 = NodeId.getDefaultInstance("openflow:2");
- roleManagerSpy.setRoleContext(nodeId, roleContextSpy);
- roleManagerSpy.servicesChangeDone(nodeId2, true);
+ roleManagerSpy.setRoleContext(deviceInfo, roleContextSpy);
+ roleManagerSpy.servicesChangeDone(deviceInfo2, true);
verify(roleContextSpy, never()).unregisterCandidate(Mockito.<Entity>any());
}
}
\ No newline at end of file
package org.opendaylight.openflowplugin.impl.rpc;
import static org.junit.Assert.assertNotNull;
+
import java.util.concurrent.Future;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
*/
package org.opendaylight.openflowplugin.impl.rpc;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static org.junit.Assert.assertEquals;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.XidSequencer;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
-import java.util.concurrent.Semaphore;
@RunWith(MockitoJUnitRunner.class)
public class RpcContextImplTest {
private NotificationPublishService notificationPublishService;
@Mock
private TestRpcService serviceInstance;
+ @Mock
+ private DeviceInfo deviceInfo;
private KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
nodeInstanceIdentifier = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(nodeId));
when(deviceContext.getDeviceState()).thenReturn(deviceState);
- when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodeInstanceIdentifier);
+ when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(nodeInstanceIdentifier);
when(deviceContext.getMessageSpy()).thenReturn(messageSpy);
rpcContext = new RpcContextImpl(rpcProviderRegistry,deviceContext, messageSpy, MAX_REQUESTS,nodeInstanceIdentifier);
*/
package org.opendaylight.openflowplugin.impl.rpc;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
import com.google.common.base.VerifyException;
+import java.util.concurrent.ConcurrentMap;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
-import java.util.concurrent.ConcurrentMap;
-
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
@RunWith(MockitoJUnitRunner.class)
public class RpcManagerImplTest {
@Mock
private RpcContext removedContexts;
@Mock
- private ConcurrentMap<NodeId, RpcContext> contexts;
+ private ConcurrentMap<DeviceInfo, RpcContext> contexts;
+ @Mock
+ private DeviceInfo deviceInfo;
@Rule
public ExpectedException expectedException = ExpectedException.none();
Mockito.when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
Mockito.when(deviceContext.getItemLifeCycleSourceRegistry()).thenReturn(itemLifeCycleRegistry);
- Mockito.when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodePath);
- Mockito.when(deviceState.getFeatures()).thenReturn(featuresOutput);
+ Mockito.when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(nodePath);
rpcManager.setDeviceTerminationPhaseHandler(deviceTerminationPhaseHandler);
Mockito.when(connectionContext.getFeatures()).thenReturn(features);
Mockito.when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
Mockito.when(deviceContext.getItemLifeCycleSourceRegistry()).thenReturn(itemLifeCycleRegistry);
- Mockito.when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodePath);
+ Mockito.when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(nodePath);
Mockito.when(deviceContext.getMessageSpy()).thenReturn(messageSpy);
- Mockito.when(deviceState.getNodeId()).thenReturn(nodeKey.getId());
+ Mockito.when(deviceInfo.getNodeId()).thenReturn(nodeKey.getId());
Mockito.when(rpcProviderRegistry.addRoutedRpcImplementation(
Matchers.<Class<RpcService>>any(), Matchers.any(RpcService.class)))
.thenReturn(routedRpcRegistration);
- Mockito.when(conductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(deviceContext);
- Mockito.when(contexts.remove(nodeId)).thenReturn(removedContexts);
+ Mockito.when(conductor.getDeviceContext(deviceInfo)).thenReturn(deviceContext);
+ Mockito.when(contexts.remove(deviceInfo)).thenReturn(removedContexts);
}
@Test
public void onDeviceContextLevelUp() throws Exception {
- rpcManager.onDeviceContextLevelUp(nodeId);
- verify(conductor).getDeviceContext(Mockito.<NodeId>any());
+ rpcManager.onDeviceContextLevelUp(deviceInfo);
+ verify(conductor).getDeviceContext(deviceInfo);
}
@Test
public void onDeviceContextLevelUpTwice() throws Exception {
- rpcManager.onDeviceContextLevelUp(nodeId);
+ rpcManager.onDeviceContextLevelUp(deviceInfo);
expectedException.expect(VerifyException.class);
- rpcManager.onDeviceContextLevelUp(nodeId);
+ rpcManager.onDeviceContextLevelUp(deviceInfo);
}
@Test
public void testOnDeviceContextLevelUpMaster() throws Exception {
- rpcManager.onDeviceContextLevelUp(nodeId);
- verify(deviceINitializationPhaseHandler).onDeviceContextLevelUp(nodeId);
+ rpcManager.onDeviceContextLevelUp(deviceInfo);
+ verify(deviceINitializationPhaseHandler).onDeviceContextLevelUp(deviceInfo);
}
@Test
public void testOnDeviceContextLevelUpSlave() throws Exception {
- rpcManager.onDeviceContextLevelUp(nodeId);
- verify(deviceINitializationPhaseHandler).onDeviceContextLevelUp(nodeId);
+ rpcManager.onDeviceContextLevelUp(deviceInfo);
+ verify(deviceINitializationPhaseHandler).onDeviceContextLevelUp(deviceInfo);
}
@Test
public void testOnDeviceContextLevelUpOther() throws Exception {
- rpcManager.onDeviceContextLevelUp(nodeId);
- verify(deviceINitializationPhaseHandler).onDeviceContextLevelUp(nodeId);
+ rpcManager.onDeviceContextLevelUp(deviceInfo);
+ verify(deviceINitializationPhaseHandler).onDeviceContextLevelUp(deviceInfo);
}
@Test
public void testOnDeviceContextLevelDown() throws Exception {
- rpcManager.onDeviceContextLevelDown(deviceContext);
- verify(deviceTerminationPhaseHandler).onDeviceContextLevelDown(deviceContext);
+ rpcManager.onDeviceContextLevelDown(deviceInfo);
+ verify(deviceTerminationPhaseHandler).onDeviceContextLevelDown(deviceInfo);
}
/**
*/
@Test
public void onDeviceContextLevelDown1() {
- rpcManager.addRecordToContexts(nodeId,removedContexts);
- rpcManager.onDeviceContextLevelDown(deviceContext);
+ rpcManager.addRecordToContexts(deviceInfo,removedContexts);
+ rpcManager.onDeviceContextLevelDown(deviceInfo);
verify(removedContexts,times(1)).close();
- verify(deviceTerminationPhaseHandler,times(1)).onDeviceContextLevelDown(deviceContext);
+ verify(deviceTerminationPhaseHandler,times(1)).onDeviceContextLevelDown(deviceInfo);
}
*/
@Test
public void onDeviceContextLevelDown2() {
- rpcManager.onDeviceContextLevelDown(deviceContext);
+ rpcManager.onDeviceContextLevelDown(deviceInfo);
verify(removedContexts,never()).close();
- verify(deviceTerminationPhaseHandler,times(1)).onDeviceContextLevelDown(deviceContext);
+ verify(deviceTerminationPhaseHandler,times(1)).onDeviceContextLevelDown(deviceInfo);
}
@Test
public void close() {
- rpcManager.addRecordToContexts(nodeId,removedContexts);
+ rpcManager.addRecordToContexts(deviceInfo,removedContexts);
rpcManager.close();
verify(removedContexts,atLeastOnce()).close();
}
package org.opendaylight.openflowplugin.impl.services;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.openflowjava.protocol.api.connection.DeviceRequestFailedException;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
-import java.util.Collection;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
public class AbstractRequestCallbackTest {
private static final Class<?> DUMMY_REQUEST_TYPE = String.class;
private SendBarrierInput buildSendBarrierInput() {
return new SendBarrierInputBuilder()
- .setNode(new NodeRef(mockedDeviceState.getNodeInstanceIdentifier())).build();
+ .setNode(new NodeRef(mockedDeviceInfo.getNodeInstanceIdentifier())).build();
}
}
\ No newline at end of file
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
@Mock
private DeviceState mockedDeviceState;
@Mock
+ private DeviceInfo mockedDeviceInfo;
+ @Mock
private GetFeaturesOutput mocketGetFeaturesOutput;
@Mock
private DeviceFlowRegistry mockedFlowRegistry;
when(mocketGetFeaturesOutput.getDatapathId()).thenReturn(BigInteger.valueOf(123L));
when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimaryConnection);
- when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(NODE_PATH);
- when(mockedDeviceState.getFeatures()).thenReturn(mocketGetFeaturesOutput);
+ when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(NODE_PATH);
when(mockedDeviceState.deviceSynchronized()).thenReturn(true);
- when(mockedDeviceState.getNodeId()).thenReturn(mockedNodeId);
+ when(mockedDeviceInfo.getNodeId()).thenReturn(mockedNodeId);
+ when(mockedDeviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
+ when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(mockedFlowRegistry);
- final InstanceIdentifier<FlowCapableNode> nodePath = mockedDeviceState.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+ final InstanceIdentifier<FlowCapableNode> nodePath = mockedDeviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
final FlowCapableNodeBuilder flowNodeBuilder = new FlowCapableNodeBuilder();
flowNodeBuilder.setTable(Collections.<Table> emptyList());
final Optional<FlowCapableNode> flowNodeOpt = Optional.of(flowNodeBuilder.build());
}
};
multipartRequestOnTheFlyCallback = new MultipartRequestOnTheFlyCallback(dummyRequestContext, String.class,
- mockedDeviceContext.getMessageSpy(),dummyEventIdentifier, mockedDeviceContext.getDeviceState(),
+ mockedDeviceContext.getMessageSpy(),dummyEventIdentifier, mockedDeviceInfo,
mockedDeviceContext.getDeviceFlowRegistry(), mockedDeviceContext);
}
.setMultipartReplyBody(multipartReplyFlowCaseBuilder.build())
.setXid(21L);
- final InstanceIdentifier<FlowCapableNode> nodePath = mockedDeviceState.getNodeInstanceIdentifier()
+ final InstanceIdentifier<FlowCapableNode> nodePath = mockedDeviceInfo.getNodeInstanceIdentifier()
.augmentation(FlowCapableNode.class);
final FlowCapableNodeBuilder flowNodeBuilder = new FlowCapableNodeBuilder();
final TableBuilder tableDataBld = new TableBuilder();
private TransmitPacketInput buildTransmitPacketInput() {
TransmitPacketInputBuilder transmitPacketInputBld = new TransmitPacketInputBuilder()
.setBufferId(OFConstants.OFP_NO_BUFFER)
- .setNode(new NodeRef(mockedDeviceState.getNodeInstanceIdentifier()))
+ .setNode(new NodeRef(mockedDeviceInfo.getNodeInstanceIdentifier()))
.setPayload(ULTIMATE_PAYLOAD.getBytes())
.setEgress(new NodeConnectorRef(pathToNodeconnector));
return transmitPacketInputBld.build();
@Override
protected void setup() {
- salExperimenterMessageService = new SalExperimenterMessageServiceImpl(mockedRequestContextStack, mockedDeviceContext);
+ salExperimenterMessageService = new SalExperimenterMessageServiceImpl(mockedRequestContextStack, mockedDeviceContext, extensionConverterProvider);
Mockito.when(mockedDeviceContext.getExtensionConverterProvider()).thenReturn(extensionConverterProvider);
Mockito.when(extensionConverterProvider.getMessageConverter(Matchers.<TypeVersionKey>any()))
.thenReturn(extensionConverter);
private SendExperimenterInput buildSendExperimenterInput() {
SendExperimenterInputBuilder sendExperimenterInputBld = new SendExperimenterInputBuilder()
- .setNode(new NodeRef(mockedDeviceState.getNodeInstanceIdentifier()))
+ .setNode(new NodeRef(mockedDeviceInfo.getNodeInstanceIdentifier()))
.setExperimenterMessageOfChoice(new DummyExperimenter());
return sendExperimenterInputBld.build();
}
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
@Mock
private DeviceState mockedDeviceState;
@Mock
+ private DeviceInfo mockedDeviceInfo;
+ @Mock
private DeviceFlowRegistry deviceFlowRegistry;
@Mock
private GetFeaturesOutput mockedFeaturesOutput;
when(requestContext.getXid()).thenReturn(new Xid(84L));
when(requestContext.getFuture()).thenReturn(RpcResultBuilder.success().buildFuture());
- when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(NODE_II);
- when(mockedDeviceState.getFeatures()).thenReturn(mockedFeaturesOutput);
+ when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(NODE_II);
+ when(mockedDeviceInfo.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
+ when(mockedDeviceInfo.getVersion()).thenReturn(DUMMY_VERSION);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
+ when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
salFlowService = new SalFlowServiceImpl(mockedRequestContextStack, mockedDeviceContext);
}
package org.opendaylight.openflowplugin.impl.services;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroup;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroup;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
public class SalGroupServiceImplTest extends ServiceMocking {
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.MeterKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
+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.OriginalMeter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeter;
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.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
public class SalMeterServiceImplTest extends ServiceMocking {
import static org.mockito.Mockito.verify;
import com.google.common.collect.Lists;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.port.update.UpdatedPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.port.update.UpdatedPortBuilder;
-import java.util.List;
@RunWith(MockitoJUnitRunner.class)
public class SalPortServiceImplTest extends ServiceMocking {
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+
import com.google.common.util.concurrent.ListenableFuture;
import java.math.BigInteger;
import java.util.concurrent.Future;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
@Mock
private DeviceState mockDeviceState;
+ @Mock
+ private DeviceInfo mockDeviceInfo;
+
@Mock
private GetFeaturesOutput mockFeaturesOutput;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- Mockito.when(mockDeviceState.getNodeId()).thenReturn(testNodeId);
- Mockito.when(mockDeviceState.getFeatures()).thenReturn(mockFeaturesOutput);
+ Mockito.when(mockDeviceInfo.getNodeId()).thenReturn(testNodeId);
+ Mockito.when(mockDeviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
Mockito.when(mockFeaturesOutput.getVersion()).thenReturn(testVersion);
Mockito.when(mockDeviceContext.getDeviceState()).thenReturn(mockDeviceState);
+ Mockito.when(mockDeviceContext.getDeviceInfo()).thenReturn(mockDeviceInfo);
Mockito.when(mockDeviceContext.getPrimaryConnectionContext()).thenReturn(mockConnectionContext);
Mockito.when(mockConnectionContext.getFeatures()).thenReturn(mockFeaturesReply);
Mockito.when(mockConnectionContext.getNodeId()).thenReturn(testNodeId);
package org.opendaylight.openflowplugin.impl.services;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.HashedWheelTimer;
import java.math.BigInteger;
import java.util.List;
import org.junit.Before;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
@Mock
protected DeviceState mockedDeviceState;
@Mock
+ protected DeviceInfo mockedDeviceInfo;
+ @Mock
protected DeviceInitializationPhaseHandler mockedDevicePhaseHandler;
@Mock
protected RequestContext mockedRequestContext;
when(mockedPrimConnectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
when(mockedPrimConnectionContext.getOutboundQueueProvider()).thenReturn(mockedOutboundQueue);
- when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(NODE_II);
- when(mockedDeviceState.getFeatures()).thenReturn(mockedFeaturesOutput);
+ when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(NODE_II);
+ when(mockedDeviceInfo.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
+ when(mockedDeviceInfo.getVersion()).thenReturn(DUMMY_VERSION);
when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimConnectionContext);
when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessagSpy);
when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl());
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
+ when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
when(mockedDeviceContext.getMultiMsgCollector(Matchers.<RequestContext<List<MultipartReply>>>any())).thenReturn(multiMessageCollector);
setup();
package org.opendaylight.openflowplugin.impl.statistics;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter64;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdatedBuilder;
-//import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.*;
-
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.GroupStatsBuilder;
import com.google.common.collect.Lists;
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.List;
import org.junit.Test;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionAware;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.MultipartReplyBody;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.aggregate._case.MultipartReplyAggregate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupDescCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.aggregate._case.MultipartReplyAggregateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStats;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.GroupStatsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.group.stats.BucketStats;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.MultipartReplyGroupDesc;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.MultipartReplyGroupDescBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.multipart.reply.group.desc.GroupDesc;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.multipart.reply.group.desc.GroupDescBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStats;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStatsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStatsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
import org.opendaylight.yangtools.yang.binding.DataObject;
-import javax.sql.rowset.spi.TransactionalWriter;
-import java.math.BigInteger;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
public class SinglePurposeMultipartReplyTranslatorTest {
private static final BigInteger DUMMY_DATAPATH_ID = new BigInteger("21");
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import java.math.BigInteger;
import org.junit.Before;
-import org.mockito.Mockito;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
StatisticsGatheringService mockedStatisticsGatheringService;
StatisticsGatheringOnTheFlyService mockedStatisticsOnFlyGatheringService;
ConnectionContext mockedConnectionContext;
+ DeviceInfo mockedDeviceInfo;
static final KeyedInstanceIdentifier<Node, NodeKey> dummyNodeII = InstanceIdentifier.create(Nodes.class)
.child(Node.class, new NodeKey(new NodeId("dummyNodeId")));
mockedStatisticsOnFlyGatheringService = mock(StatisticsGatheringOnTheFlyService.class);
mockedConnectionContext = mock(ConnectionContext.class);
mockedDeviceState = mock(DeviceState.class);
+ mockedDeviceInfo = mock(DeviceInfo.class);
final FeaturesReply mockedFeatures = mock(FeaturesReply.class);
final MessageSpy mockedMessageSpy = mock(MessageSpy.class);
final OutboundQueue mockedOutboundQueue = mock(OutboundQueue.class);
final DeviceManager mockedDeviceManager = mock(DeviceManager.class);
- final GetFeaturesOutput mockedFeaturesOutput = mock(GetFeaturesOutput.class);
mockConductor = mock(LifecycleConductor.class);
+ when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
+ when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
+ when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedConnectionContext);
+ when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessageSpy);
+
when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(isTable);
when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(isFlow);
when(mockedDeviceState.isGroupAvailable()).thenReturn(isGroup);
when(mockedDeviceState.isMetersAvailable()).thenReturn(isMeter);
when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(isPort);
when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(isQueue);
- when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(dummyNodeII);
- when(mockedDeviceState.getFeatures()).thenReturn(mockedFeaturesOutput);
+ when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(dummyNodeII);
+ when(mockedDeviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
+ when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedConnectionContext);
when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessageSpy);
+ when(mockedDeviceInfo.getNodeId()).thenReturn(dummyNodeII.getKey().getId());
when(mockedConnectionContext.getNodeId()).thenReturn(dummyNodeII.getKey().getId());
when(mockedConnectionContext.getFeatures()).thenReturn(mockedFeatures);
when(mockedConnectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
when(mockedConnectionContext.getOutboundQueueProvider()).thenReturn(mockedOutboundQueue);
- when(mockedDeviceManager.getDeviceContextFromNodeId(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
- mockConductor.setSafelyDeviceManager(mockedDeviceManager);
- when(mockConductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
+ mockConductor.setSafelyManager(mockedDeviceManager);
+ when(mockConductor.getDeviceContext(mockedDeviceInfo)).thenReturn(mockedDeviceContext);
}
}
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
+
import com.google.common.util.concurrent.ListenableFuture;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import org.mockito.Mockito;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
import org.opendaylight.yangtools.yang.common.RpcResult;
public void gatherDynamicDataTest() {
- final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext.getDeviceState().getNodeId(), false, mockConductor);
+ final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceInfo, false, mockConductor);
final ListenableFuture<RpcResult<List<MultipartReply>>> rpcResult = immediateFuture(RpcResultBuilder.success(Collections.<MultipartReply>emptyList()).build());
when(mockedStatisticsGatheringService.getStatisticsOfType(any(EventIdentifier.class), any(MultipartType
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
@Before
public void setUp() throws Exception {
when(mockedDeviceContext.reserveXidForDeviceMessage()).thenReturn(TEST_XID);
- when(mockConductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
+ when(mockConductor.getDeviceContext(mockedDeviceInfo)).thenReturn(mockedDeviceContext);
initStatisticsContext();
}
private void initStatisticsContext() {
- statisticsContext = new StatisticsContextImpl(mockedDeviceContext.getDeviceState().getNodeId(), false, mockConductor);
+ statisticsContext = new StatisticsContextImpl(mockedDeviceInfo, false, mockConductor);
statisticsContext.setStatisticsGatheringService(mockedStatisticsGatheringService);
statisticsContext.setStatisticsGatheringOnTheFlyService(mockedStatisticsOnFlyGatheringService);
}
*/
@Test
public void testClose() throws Exception {
- final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext.getDeviceState().getNodeId(), false, mockConductor);
+ final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceInfo, false, mockConductor);
final RequestContext<Object> requestContext = statisticsContext.createRequestContext();
statisticsContext.close();
try {
@Test
public void testGatherDynamicData_all() throws Exception {
Mockito.reset(mockedDeviceState);
- when(mockedDeviceState.getFeatures()).thenReturn(mock(GetFeaturesOutput.class));
when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.isGroupAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.isMetersAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(Boolean.TRUE);
- when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(dummyNodeII);
+ when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(dummyNodeII);
initStatisticsContext();
when(mockedStatisticsGatheringService.getStatisticsOfType(Matchers.any(EventIdentifier.class), Matchers.any(MultipartType.class)))
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.CheckedFuture;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
@RunWith(MockitoJUnitRunner.class)
public class StatisticsGatheringUtilsTest {
- public static final String DUMMY_NODE_ID_VALUE = "1";
- public static final NodeId DUMMY_NODE_ID = new NodeId(DUMMY_NODE_ID_VALUE);
+ static final String DUMMY_NODE_ID_VALUE = "1";
+ static final NodeId DUMMY_NODE_ID = new NodeId(DUMMY_NODE_ID_VALUE);
private final KeyedInstanceIdentifier<Node, NodeKey> dummyNodePath = InstanceIdentifier.create(Nodes.class)
.child(Node.class, new NodeKey(DUMMY_NODE_ID));
private ConnectionContext connectionAdapter;
@Mock
private StatisticsGatherer statisticsService;
+ @Mock
+ private DeviceInfo deviceInfo;
+ @Mock
+ private TxFacade txFacade;
public StatisticsGatheringUtilsTest() {
OpenflowPortsUtil.init();
@Before
public void setUp() throws Exception {
when(deviceContext.getDeviceState()).thenReturn(deviceState);
+ when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
when(deviceContext.getDeviceFlowRegistry()).thenReturn(deviceFlowRegistry);
when(deviceContext.getDeviceGroupRegistry()).thenReturn(deviceGroupRegistry);
when(deviceContext.getDeviceMeterRegistry()).thenReturn(deviceMeterRegistry);
when(deviceContext.getReadTransaction()).thenReturn(readTx);
+ when(txFacade.getReadTransaction()).thenReturn(readTx);
when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionAdapter);
when(connectionAdapter.getNodeId()).thenReturn(DUMMY_NODE_ID);
- when(deviceState.getFeatures()).thenReturn(features);
when(connectionAdapter.getFeatures()).thenReturn(features);
-
- when(features.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
when(features.getDatapathId()).thenReturn(BigInteger.ONE);
+ when(features.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
- when(deviceState.getNodeInstanceIdentifier()).thenReturn(dummyNodePath);
+ when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+ when(deviceInfo.getDatapathId()).thenReturn(BigInteger.ONE);
+ when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(dummyNodePath);
+ when(deviceInfo.getNodeId()).thenReturn(DUMMY_NODE_ID);
}
@After
final ArgumentCaptor<Flow> flow = ArgumentCaptor.forClass(Flow.class);
StatisticsGatheringUtils.writeFlowStatistics(prepareFlowStatisticsData(),
- deviceContext.getDeviceState(), deviceContext.getDeviceFlowRegistry(), deviceContext);
+ deviceInfo, deviceContext.getDeviceFlowRegistry(), deviceContext);
Mockito.verify(deviceContext).writeToTransaction(
dataStoreType.capture(), flowPath.capture(), flow.capture());
.child(Group.class, new GroupKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId(groupIdValue)))
.augmentation(NodeGroupStatistics.class)
.child(GroupStatistics.class);
- verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
+ verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
Matchers.eq(groupPath), Matchers.any(GroupStatistics.class));
}
verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>> any());
verify(deviceGroupRegistry).removeMarked();
verify(deviceGroupRegistry).store(storedGroupId);
- verify(deviceContext).writeToTransaction(
+ verify(txFacade).writeToTransaction(
Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(groupPath), Matchers.any(Group.class));
}
.child(Meter.class, new MeterKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId(meterIdValue)))
.augmentation(NodeMeterStatistics.class)
.child(MeterStatistics.class);
- verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
+ verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
Matchers.eq(meterPath), Matchers.any(MeterStatistics.class));
}
.child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:" + DUMMY_NODE_ID_VALUE + ":11")))
.augmentation(FlowCapableNodeConnectorStatisticsData.class)
.child(FlowCapableNodeConnectorStatistics.class);
- verify(deviceContext).writeToTransaction(
+ verify(txFacade).writeToTransaction(
Matchers.eq(LogicalDatastoreType.OPERATIONAL),
Matchers.eq(portPath),
Matchers.any(FlowCapableNodeConnectorStatistics.class));
.child(Table.class, new TableKey((short) 0))
.augmentation(FlowTableStatisticsData.class)
.child(FlowTableStatistics.class);
- verify(deviceContext).writeToTransaction(
+ verify(txFacade).writeToTransaction(
Matchers.eq(LogicalDatastoreType.OPERATIONAL),
Matchers.eq(tablePath),
Matchers.any(FlowTableStatistics.class));
.child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:" + DUMMY_NODE_ID_VALUE + ":11")))
.augmentation(FlowCapableNodeConnector.class)
.child(Queue.class, new QueueKey(new QueueId(queueIdValue)));
- verify(deviceContext).writeToTransaction(
+ verify(txFacade).writeToTransaction(
Matchers.eq(LogicalDatastoreType.OPERATIONAL),
Matchers.eq(queuePath),
Matchers.any(Queue.class));
@Test
public void testGatherStatistics_flow() throws Exception {
+ final short tableId = 0;
final MultipartType type = MultipartType.OFPMPFLOW;
when(deviceFlowRegistry.storeIfNecessary(Matchers.any(FlowRegistryKey.class), Matchers.anyShort()))
.thenReturn(new FlowId("openflow:21"));
+ final InstanceIdentifier<FlowCapableNode> nodePath = deviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+ final TableBuilder tableDataBld = new TableBuilder();
+ tableDataBld.setId(tableId);
+ final FlowCapableNodeBuilder flowNodeBuilder = new FlowCapableNodeBuilder();
+ flowNodeBuilder.setTable(Collections.singletonList(tableDataBld.build()));
+ final Optional<FlowCapableNode> flowNodeOpt = Optional.of(flowNodeBuilder.build());
+ final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> flowNodeFuture = Futures.immediateCheckedFuture(flowNodeOpt);
+ when(readTx.read(LogicalDatastoreType.OPERATIONAL, nodePath)).thenReturn(flowNodeFuture);
+
final org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder matchBld =
new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder()
.setMatchEntry(Collections.<MatchEntry>emptyList());
.child(Flow.class, new FlowKey(new FlowId("openflow:21")));
verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>>any());
verify(deviceFlowRegistry).storeIfNecessary(FlowRegistryKeyFactory.create(flowBld.build()), (short) 0);
- verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(flowPath), Matchers.any(Flow.class));
+ verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(flowPath), Matchers.any(Flow.class));
}
@Test
.child(Meter.class, new MeterKey(meterId));
verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>>any());
verify(deviceMeterRegistry).store(meterId);
- verify(deviceContext).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(meterPath), Matchers.any(Meter.class));
+ verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(meterPath), Matchers.any(Meter.class));
}
private void fireAndCheck(final MultipartType type, final List<MultipartReply> statsData) throws InterruptedException, ExecutionException, TimeoutException {
when(statisticsService.getStatisticsOfType(Matchers.any(EventIdentifier.class), Matchers.eq(type)))
.thenReturn(Futures.immediateFuture(RpcResultBuilder.success(statsData).build()));
- final ListenableFuture<Boolean> gatherStatisticsResult = StatisticsGatheringUtils.gatherStatistics(statisticsService, deviceContext, type);
+ final ListenableFuture<Boolean> gatherStatisticsResult = StatisticsGatheringUtils.gatherStatistics(
+ statisticsService,
+ deviceInfo,
+ type,
+ txFacade,
+ deviceContext,
+ false);
Assert.assertTrue(gatherStatisticsResult.get(1, TimeUnit.SECONDS).booleanValue());
- verify(deviceContext).submitTransaction();
+ verify(txFacade).submitTransaction();
}
private static MultipartReplyMessage assembleMPReplyMessage(final MultipartType type, final MultipartReplyBody mpReplyGroupCaseBld) {
return new BucketStatsBuilder().setByteCount(BigInteger.valueOf(byteCount)).setPacketCount(BigInteger.valueOf(packetCount)).build();
}
- @Test
- public void testDeleteAllKnownFlowsNotSync() throws Exception {
- when(deviceState.deviceSynchronized()).thenReturn(false);
- StatisticsGatheringUtils.deleteAllKnownFlows(deviceContext.getDeviceState(),
- deviceContext.getDeviceFlowRegistry(), deviceContext);
- Mockito.verifyNoMoreInteractions(deviceFlowRegistry);
- }
-
@Test
public void testDeleteAllKnownFlows() throws Exception {
final short tableId = 0;
when(deviceState.deviceSynchronized()).thenReturn(true);
- final InstanceIdentifier<FlowCapableNode> nodePath = deviceState.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
+ final InstanceIdentifier<FlowCapableNode> nodePath = deviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
final TableBuilder tableDataBld = new TableBuilder();
tableDataBld.setId(tableId);
final FlowCapableNodeBuilder flowNodeBuilder = new FlowCapableNodeBuilder();
final Optional<FlowCapableNode> flowNodeOpt = Optional.of(flowNodeBuilder.build());
final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> flowNodeFuture = Futures.immediateCheckedFuture(flowNodeOpt);
when(readTx.read(LogicalDatastoreType.OPERATIONAL, nodePath)).thenReturn(flowNodeFuture);
- final KeyedInstanceIdentifier<Table, TableKey> tablePath = deviceState.getNodeInstanceIdentifier()
+ final KeyedInstanceIdentifier<Table, TableKey> tablePath = deviceInfo.getNodeInstanceIdentifier()
.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId));
- StatisticsGatheringUtils.deleteAllKnownFlows(deviceContext.getDeviceState(),
- deviceContext.getDeviceFlowRegistry(), deviceContext);
+ StatisticsGatheringUtils.deleteAllKnownFlows(deviceInfo,
+ deviceContext.getDeviceFlowRegistry(), txFacade);
- verify(deviceContext).writeToTransaction(
+ verify(txFacade).writeToTransaction(
LogicalDatastoreType.OPERATIONAL,
tablePath,
tableDataBld.setFlow(Collections.<Flow>emptyList()).build());
*/
package org.opendaylight.openflowplugin.impl.statistics;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import com.google.common.base.Optional;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import io.netty.util.HashedWheelTimer;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
-
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
-import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.openflowplugin.impl.registry.flow.DeviceFlowRegistryImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.GetStatisticsWorkModeOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.StatisticsManagerControlService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.StatisticsWorkMode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
private static final BigInteger DUMMY_DATAPATH_ID = new BigInteger("444");
private static final Short DUMMY_VERSION = OFConstants.OFP_VERSION_1_3;
+ public static final NodeId NODE_ID = new NodeId("ofp-unit-dummy-node-id");
@Mock
RequestContextStack mockedRequestContextStack;
@Mock
DeviceState mockedDeviceState;
@Mock
+ DeviceInfo mockedDeviceInfo;
+ @Mock
DeviceInitializationPhaseHandler mockedDevicePhaseHandler;
@Mock
DeviceTerminationPhaseHandler mockedTerminationPhaseHandler;
private GetFeaturesOutput featuresOutput;
@Mock
private DeviceInitializationPhaseHandler deviceInitializationPhaseHandler;
+ @Mock
+ private DeviceInfo deviceInfo;
private RequestContext<List<MultipartReply>> currentRequestContext;
private StatisticsManagerImpl statisticsManager;
.create(Nodes.class)
.child(Node.class, new NodeKey(new NodeId("openflow:10")));
- when(mockedFeatures.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
- when(mockedFeatures.getVersion()).thenReturn(DUMMY_VERSION);
- when(mockedFeaturesOutput.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
- when(mockedFeaturesOutput.getVersion()).thenReturn(DUMMY_VERSION);
-
when(mockedPrimConnectionContext.getFeatures()).thenReturn(mockedFeatures);
when(mockedPrimConnectionContext.getConnectionAdapter()).thenReturn(mockedConnectionAdapter);
when(mockedPrimConnectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
- when(mockedPrimConnectionContext.getNodeId()).thenReturn(new NodeId("ut-node:123"));
+ when(mockedPrimConnectionContext.getNodeId()).thenReturn(NODE_ID);
when(mockedPrimConnectionContext.getOutboundQueueProvider()).thenReturn(outboundQueue);
when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(Boolean.TRUE);
- when(mockedDeviceState.getFeatures()).thenReturn(featuresOutput);
- when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(nodePath);
-
- when(mockedDeviceState.getNodeId()).thenReturn(new NodeId("ofp-unit-dummy-node-id"));
+ when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(nodePath);
+ when(mockedDeviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
+ when(mockedDeviceInfo.getNodeId()).thenReturn(new NodeId("ofp-unit-dummy-node-id"));
+ when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimConnectionContext);
when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessagSpy);
when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl());
statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, false, conductor);
statisticsManager.setDeviceInitializationPhaseHandler(deviceInitializationPhaseHandler);
- when(deviceManager.getDeviceContextFromNodeId(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
- when(conductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
+ when(conductor.getDeviceContext(deviceInfo)).thenReturn(mockedDeviceContext);
}
@Test
.commitEntry(Matchers.anyLong(), Matchers.<OfHeader>any(), Matchers.<FutureCallback<OfHeader>>any());
statisticsManager.setDeviceInitializationPhaseHandler(mockedDevicePhaseHandler);
- statisticsManager.onDeviceContextLevelUp(mockedDeviceContext.getDeviceState().getNodeId());
- verify(mockedDevicePhaseHandler).onDeviceContextLevelUp(mockedDeviceContext.getDeviceState().getNodeId());
+ statisticsManager.onDeviceContextLevelUp(deviceInfo);
+ verify(mockedDevicePhaseHandler).onDeviceContextLevelUp(deviceInfo);
}
@Test
public void testOnDeviceContextClosed() throws Exception {
final StatisticsContext statisticContext = Mockito.mock(StatisticsContext.class);
- final Map<NodeId, StatisticsContext> contextsMap = getContextsMap(statisticsManager);
+ final Map<DeviceInfo, StatisticsContext> contextsMap = getContextsMap(statisticsManager);
- contextsMap.put(mockedDeviceContext.getDeviceState().getNodeId(), statisticContext);
+ contextsMap.put(deviceInfo, statisticContext);
Assert.assertEquals(1, contextsMap.size());
statisticsManager.setDeviceTerminationPhaseHandler(mockedTerminationPhaseHandler);
- statisticsManager.onDeviceContextLevelDown(mockedDeviceContext);
+ statisticsManager.onDeviceContextLevelDown(deviceInfo);
verify(statisticContext).close();
- verify(mockedTerminationPhaseHandler).onDeviceContextLevelDown(mockedDeviceContext);
+ verify(mockedTerminationPhaseHandler).onDeviceContextLevelDown(deviceInfo);
Assert.assertEquals(0, contextsMap.size());
}
- private static Map<NodeId, StatisticsContext> getContextsMap(final StatisticsManagerImpl statisticsManager)
+ private static Map<DeviceInfo, StatisticsContext> getContextsMap(final StatisticsManagerImpl statisticsManager)
throws NoSuchFieldException, IllegalAccessException {
// HACK: contexts map for testing shall be accessed in some more civilized way
final Field contextsField = StatisticsManagerImpl.class.getDeclaredField("contexts");
Assert.assertNotNull(contextsField);
contextsField.setAccessible(true);
- return (Map<NodeId, StatisticsContext>) contextsField.get(statisticsManager);
+ return (Map<DeviceInfo, StatisticsContext>) contextsField.get(statisticsManager);
}
@Test
@Test
public void testChangeStatisticsWorkMode1() throws Exception {
final StatisticsContext statisticContext = Mockito.mock(StatisticsContext.class);
- when(statisticContext.getDeviceContext()).thenReturn(mockedDeviceContext);
when(statisticContext.getPollTimeout()).thenReturn(
- Optional.<Timeout>absent());
+ Optional.<Timeout>empty());
when(itemLifeCycleRegistry.getLifeCycleSources()).thenReturn(
Collections.<ItemLifeCycleSource>emptyList());
- getContextsMap(statisticsManager).put(mockedDeviceContext.getDeviceState().getNodeId(), statisticContext);
+ getContextsMap(statisticsManager).put(deviceInfo, statisticContext);
final ChangeStatisticsWorkModeInputBuilder changeStatisticsWorkModeInputBld =
new ChangeStatisticsWorkModeInputBuilder()
Mockito.verify(statisticContext).getPollTimeout();
}
- private static void checkWorkModeChangeOutcome(Future<RpcResult<Void>> workMode) throws InterruptedException, java.util.concurrent.ExecutionException {
+ private static void checkWorkModeChangeOutcome(Future<RpcResult<Void>> workMode) throws InterruptedException, ExecutionException {
Assert.assertTrue(workMode.isDone());
Assert.assertTrue(workMode.get().isSuccessful());
}
final Timeout pollTimeout = Mockito.mock(Timeout.class);
final ItemLifeCycleSource itemLifecycleSource = Mockito.mock(ItemLifeCycleSource.class);
final StatisticsContext statisticContext = Mockito.mock(StatisticsContext.class);
- when(statisticContext.getDeviceContext()).thenReturn(mockedDeviceContext);
when(statisticContext.getPollTimeout()).thenReturn(
Optional.of(pollTimeout));
when(itemLifeCycleRegistry.getLifeCycleSources()).thenReturn(
Collections.singletonList(itemLifecycleSource));
- getContextsMap(statisticsManager).put(mockedDeviceContext.getDeviceState().getNodeId(), statisticContext);
+ getContextsMap(statisticsManager).put(deviceInfo, statisticContext);
final ChangeStatisticsWorkModeInputBuilder changeStatisticsWorkModeInputBld =
new ChangeStatisticsWorkModeInputBuilder()
.setItemLifecycleListener(itemLifeCycleListenerCapt.capture());
final StatisticsContext statisticContext = Mockito.mock(StatisticsContext.class);
- when(statisticContext.getDeviceContext()).thenReturn(mockedDeviceContext);
when(statisticContext.getPollTimeout()).thenReturn(
Optional.of(pollTimeout));
when(statisticContext.getItemLifeCycleListener()).thenReturn(
when(itemLifeCycleRegistry.getLifeCycleSources()).thenReturn(
Collections.singletonList(itemLifecycleSource));
- getContextsMap(statisticsManager).put(mockedDeviceContext.getDeviceState().getNodeId(), statisticContext);
+ getContextsMap(statisticsManager).put(deviceInfo, statisticContext);
final ChangeStatisticsWorkModeInputBuilder changeStatisticsWorkModeInputBld =
new ChangeStatisticsWorkModeInputBuilder()
@Test
public void testCalculateTimerDelay() throws Exception {
final TimeCounter timeCounter = Mockito.mock(TimeCounter.class);
- when(timeCounter.getAverageTimeBetweenMarks()).thenReturn((Long)2000L, (Long)4000L);
+ when(timeCounter.getAverageTimeBetweenMarks()).thenReturn(2000L, (Long)4000L);
statisticsManager.calculateTimerDelay(timeCounter);
Assert.assertEquals(3000L, StatisticsManagerImpl.getCurrentTimerDelay());
final StatisticsContext statisticsContext = Mockito.mock(StatisticsContext.class);
final TimeCounter mockTimerCounter = Mockito.mock(TimeCounter.class);
- statisticsManager.pollStatistics(mockedDeviceContext, statisticsContext, mockTimerCounter);
+ statisticsManager.pollStatistics(mockedDeviceContext.getDeviceState(), statisticsContext, mockTimerCounter, mockedDeviceInfo);
verify(mockedDeviceContext).getDeviceState();
when(mockedDeviceContext.getDeviceState().isValid()).thenReturn(true);
- statisticsManager.pollStatistics(mockedDeviceContext, statisticsContext, mockTimerCounter);
- // TODO Make scheduleNextPolling visible for tests?
+ statisticsManager.pollStatistics(mockedDeviceContext.getDeviceState(), statisticsContext, mockTimerCounter, mockedDeviceInfo);
when(mockedDeviceContext.getDeviceState().isStatisticsPollingEnabled()).thenReturn(true);
- statisticsManager.pollStatistics(mockedDeviceContext, statisticsContext, mockTimerCounter);
- // TODO Make scheduleNextPolling visible for tests?
+ statisticsManager.pollStatistics(mockedDeviceContext.getDeviceState(), statisticsContext, mockTimerCounter, mockedDeviceInfo);
when(statisticsContext.gatherDynamicData()).thenReturn(Futures.immediateCheckedFuture(Boolean.TRUE));
when(statisticsContext.isSchedulingEnabled()).thenReturn(Boolean.TRUE);
- statisticsManager.pollStatistics(mockedDeviceContext, statisticsContext, mockTimerCounter);
+ statisticsManager.pollStatistics(mockedDeviceContext.getDeviceState(), statisticsContext, mockTimerCounter, mockedDeviceInfo);
Mockito.verify(mockTimerCounter).markStart();
Mockito.verify(mockTimerCounter).addTimeMark();
when(statisticsContext.gatherDynamicData()).thenReturn(Futures.immediateFailedFuture(new Throwable("error msg")));
- statisticsManager.pollStatistics(mockedDeviceContext, statisticsContext, mockTimerCounter);
+ statisticsManager.pollStatistics(mockedDeviceContext.getDeviceState(), statisticsContext, mockTimerCounter, mockedDeviceInfo);
Mockito.verify(mockTimerCounter,times(2)).addTimeMark();
}
}
\ No newline at end of file
package org.opendaylight.openflowplugin.impl.statistics.ofpspecific;
-import junit.framework.TestCase;
-import org.junit.Test;
-import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
+import static org.junit.Assert.assertTrue;
import java.util.List;
-
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
public class MessageIntelligenceAgencyImplTest {
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
protected TranslatorLibrary translatorLibrary;
@Mock
protected DeviceState deviceState;
+ @Mock
+ protected DeviceInfo deviceInfo;
public static final NodeId NODE_ID = new NodeId("unit-test-node:123");
Mockito.when(deviceContext.getMultiMsgCollector(Matchers.any(RequestContext.class))).thenReturn(multiMsgCollector);
Mockito.when(deviceContext.oook()).thenReturn(translatorLibrary);
Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
- Mockito.when(deviceState.getNodeId()).thenReturn(NODE_ID);
- Mockito.when(deviceState.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
- Mockito.when(deviceState.getFeatures()).thenReturn(getFeaturesOutput);
+ Mockito.when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
+ Mockito.when(deviceInfo.getNodeId()).thenReturn(NODE_ID);
+ Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+ Mockito.when(deviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
Mockito.when(connectionContext.getFeatures()).thenReturn(features);
Mockito.when(connectionContext.getOutboundQueueProvider()).thenReturn(outboundQueueProvider);
Mockito.when(features.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
}
).when(multiMsgCollector).endCollecting(Matchers.any(EventIdentifier.class));
Mockito.when(translator.translate(
- Matchers.any(MultipartReply.class), Matchers.same(deviceState), Matchers.isNull())
+ Matchers.any(MultipartReply.class), Matchers.same(deviceInfo), Matchers.isNull())
).thenReturn(new AggregatedFlowStatisticsBuilder().build());
import org.mockito.stubbing.Answer;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
@Mock
private DeviceState deviceState;
@Mock
+ private DeviceInfo deviceInfo;
+ @Mock
private MessageTranslator<Object, Object> translator;
@Mock
private GetFeaturesOutput featuresOutput;
Mockito.when(featuresOutput.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
Mockito.when(rqContextStack.<Object>createRequestContext()).thenReturn(rqContext);
Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
- Mockito.when(deviceState.getNodeId()).thenReturn(NODE_ID);
- Mockito.when(deviceState.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
- Mockito.when(deviceState.getFeatures()).thenReturn(featuresOutput);
+ Mockito.when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
+ Mockito.when(deviceInfo.getNodeId()).thenReturn(NODE_ID);
+ Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
Mockito.doAnswer(closeRequestFutureAnswer).when(multiMsgCollector).endCollecting();
Mockito.doAnswer(closeRequestFutureAnswer).when(multiMsgCollector).endCollecting(Matchers.any(EventIdentifier.class));
.setFlowCount(new Counter32(12L))
.setPacketCount(new Counter64(BigInteger.valueOf(13L)))
.build();
- Mockito.when(translator.translate(Matchers.any(MultipartReply.class), Matchers.eq(deviceState), Matchers.any()))
+ Mockito.when(translator.translate(Matchers.any(MultipartReply.class), Matchers.eq(deviceInfo), Matchers.any()))
.thenReturn(aggregatedStats);
.setNode(createNodeRef("unitProt:123"))
.setTableId(new TableId((short) 1));
- Mockito.when(translator.translate(Matchers.any(MultipartReply.class), Matchers.eq(deviceState), Matchers.any()))
+ Mockito.when(translator.translate(Matchers.any(MultipartReply.class), Matchers.eq(deviceInfo), Matchers.any()))
.thenReturn(new AggregatedFlowStatisticsBuilder()
.setByteCount(new Counter64(BigInteger.valueOf(50L)))
.setPacketCount(new Counter64(BigInteger.valueOf(51L)))
protected void setup() {
statisticsGatheringService = new StatisticsGatheringOnTheFlyService(mockedRequestContextStack, mockedDeviceContext);
Mockito.doReturn(NODE_ID).when(mockedPrimConnectionContext).getNodeId();
- Mockito.when(mockedDeviceContext.getDeviceState().getNodeId()).thenReturn(NODE_ID);
+ Mockito.when(mockedDeviceInfo.getNodeId()).thenReturn(NODE_ID);
+ Mockito.when(mockedDeviceContext.getDeviceInfo().getNodeId()).thenReturn(NODE_ID);
}
@Test
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+import java.math.BigInteger;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import java.math.BigInteger;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.when;
-
@RunWith(MockitoJUnitRunner.class)
public abstract class AbstractDirectStatisticsServiceTest {
protected static final Long PORT_NO = 1L;
@Mock
protected DeviceState deviceState;
@Mock
+ protected DeviceInfo deviceInfo;
+ @Mock
protected GetFeaturesOutput getFeaturesOutput;
protected NodeConnectorId nodeConnectorId;
when(deviceContext.getMultiMsgCollector(any())).thenReturn(multiMsgCollector);
when(deviceContext.oook()).thenReturn(translatorLibrary);
when(deviceContext.getDeviceState()).thenReturn(deviceState);
- when(deviceContext.getDeviceState()).thenReturn(deviceState);
- when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodeInstanceIdentifier);
- when(deviceState.getNodeId()).thenReturn(new NodeId(NODE_ID));
- when(deviceState.getVersion()).thenReturn(OF_VERSION);
- when(deviceState.getFeatures()).thenReturn(getFeaturesOutput);
+ when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
+ when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(nodeInstanceIdentifier);
+ when(deviceInfo.getNodeId()).thenReturn(new NodeId(NODE_ID));
+ when(deviceInfo.getVersion()).thenReturn(OF_VERSION);
+ when(deviceInfo.getDatapathId()).thenReturn(DATAPATH_ID);
when(getFeaturesOutput.getVersion()).thenReturn(OF_VERSION);
when(getFeaturesOutput.getDatapathId()).thenReturn(DATAPATH_ID);
when(connectionContext.getFeatures()).thenReturn(features);
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetFlowStatisticsInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestFlowCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.flow._case.MultipartRequestFlow;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
public class FlowDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
static final Short TABLE_NO = 1;
private FlowDirectStatisticsService service;
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetGroupStatisticsOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.group._case.MultipartRequestGroup;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
public class GroupDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
static final Long GROUP_NO = 1L;
private GroupDirectStatisticsService service;
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetMeterStatisticsOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.meter._case.MultipartRequestMeter;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
public class MeterDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
static final Long METER_NO = 1L;
private MeterDirectStatisticsService service;
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetNodeConnectorStatisticsOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.port.stats._case.MultipartRequestPortStats;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
public class NodeConnectorDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
private NodeConnectorDirectStatisticsService service;
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
@RunWith(MockitoJUnitRunner.class)
public class OpendaylightDirectStatisticsServiceImplTest {
@Mock
package org.opendaylight.openflowplugin.impl.statistics.services.direct;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.GetQueueStatisticsOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.queue._case.MultipartRequestQueue;
import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
public class QueueDirectStatisticsServiceTest extends AbstractDirectStatisticsServiceTest {
static final Long QUEUE_NO = 1L;
private QueueDirectStatisticsService service;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.aggregate.flow.statistics.from.flow.table._for.given.match.output.AggregatedFlowStatistics;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCaseBuilder;
private AggregatedFlowStatisticsTranslator translator;
@Mock
- private DeviceState deviceState;
+ private DeviceInfo deviceInfo;
@Before
public void setUp() throws Exception {
MultipartReplyMessageBuilder mpInputBld = new MultipartReplyMessageBuilder()
.setMultipartReplyBody(inputBld.build());
- final AggregatedFlowStatistics statistics = translator.translate(mpInputBld.build(), deviceState, null);
+ final AggregatedFlowStatistics statistics = translator.translate(mpInputBld.build(), deviceInfo, null);
Assert.assertEquals(aggregateStatsValueBld.getByteCount(), statistics.getByteCount().getValue());
Assert.assertEquals(aggregateStatsValueBld.getFlowCount(), statistics.getFlowCount().getValue());
import java.math.BigInteger;
import java.util.Collections;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowWildcardsV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10Builder;
@Mock
private DeviceState deviceState;
+ @Mock
+ private DeviceInfo deviceInfo;
+
@Mock
private GetFeaturesOutput features;
translatorV10 = new FlowRemovedV10Translator();
when(deviceContext.getDeviceState()).thenReturn(deviceState);
- when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodeId);
- when(deviceState.getFeatures()).thenReturn(features);
+ when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(nodeId);
when(features.getDatapathId()).thenReturn(BigInteger.TEN);
}
@Test
public void testTranslate() throws Exception {
org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemoved flowRemovedMessage = buildMessage(false);
- final FlowRemoved flowRemoved = translator.translate(flowRemovedMessage, deviceState, null);
+ final FlowRemoved flowRemoved = translator.translate(flowRemovedMessage, deviceInfo, null);
assertEquals(flowRemovedMessage.getCookie(), flowRemoved.getCookie().getValue());
assertEquals(flowRemovedMessage.getPriority(), flowRemoved.getPriority());
@Test
public void testTranslateV10() throws Exception {
org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemoved flowRemovedMessage = buildMessage(true);
- final FlowRemoved flowRemoved = translatorV10.translate(flowRemovedMessage, deviceState, null);
+ final FlowRemoved flowRemoved = translatorV10.translate(flowRemovedMessage, deviceInfo, null);
assertEquals(flowRemovedMessage.getCookie(), flowRemoved.getCookie().getValue());
assertEquals(flowRemovedMessage.getPriority(), flowRemoved.getPriority());
- assertEquals((long)flowRemovedMessage.getTableId().getValue(), (long)flowRemoved.getTableId());
+ assertEquals((short)0, flowRemoved.getTableId().shortValue());
}
private org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemoved buildMessage(boolean isV10) {
FlowRemovedMessageBuilder builder = new FlowRemovedMessageBuilder()
.setCookie(BigInteger.ONE)
- .setPriority(1)
- .setTableId(new TableId(42l));
+ .setPriority(1);
if (isV10) {
builder.setMatchV10(new MatchV10Builder().setWildcards(flowWildcards).build());
} else {
- builder.setMatch(new MatchBuilder().setMatchEntry(Collections.<MatchEntry>emptyList()).build());
+ builder.setMatch(new MatchBuilder().setMatchEntry(Collections.<MatchEntry>emptyList()).build())
+ .setTableId(new TableId(42L));
}
return builder.build();
}
-}
\ No newline at end of file
+}
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
-
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@Mock
DeviceContext deviceContext;
@Mock
+ DeviceInfo deviceInfo;
+ @Mock
List<PhyPort> phyPorts;
@Mock
PhyPort phyPort;
Mockito.when(connectionContext.getFeatures()).thenReturn(featuresReply);
Mockito.when(featuresReply.getDatapathId()).thenReturn(BigInteger.TEN);
Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
- Mockito.when(deviceState.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
- Mockito.when(deviceState.getFeatures()).thenReturn(getFeaturesOutput);
+ Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+ Mockito.when(deviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
Mockito.when(getFeaturesOutput.getDatapathId()).thenReturn(BigInteger.TEN);
Mockito.when(getFeaturesOutput.getPhyPort()).thenReturn(phyPorts);
Mockito.when(phyPort.getPortNo()).thenReturn(PORT_NO_DS);
.child(Node.class, new NodeKey(new NodeId("openflow:10")));
final PacketReceivedTranslator packetReceivedTranslator = new PacketReceivedTranslator();
final PacketInMessage packetInMessage = createPacketInMessage(DATA.getBytes(), PORT_NO);
- Mockito.when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodePath);
+ Mockito.when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(nodePath);
- final PacketReceived packetReceived = packetReceivedTranslator.translate(packetInMessage, deviceState, null);
+ final PacketReceived packetReceived = packetReceivedTranslator.translate(packetInMessage, deviceInfo, null);
Assert.assertArrayEquals(packetInMessage.getData(), packetReceived.getPayload());
Assert.assertEquals("org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController",
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
private DeviceContext deviceContext;
@Mock
private DeviceState deviceState;
+ @Mock
+ private DeviceInfo deviceInfo;
private org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig portConfig;
private StateBuilder portStateBld;
@Before
public void setUp() throws Exception {
- Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
+ Mockito.when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
portUpdateTranslator = new PortUpdateTranslator();
portStateBld = new StateBuilder().setLive(true);
@Test
public void testTranslate_13() throws Exception {
- Mockito.when(deviceState.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+ Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures portFeatures =
org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures
.getDefaultInstance("hundredGbFd");
- final FlowCapableNodeConnector nodeConnector = portUpdateTranslator.translate(portBld.build(), deviceState, null);
+ final FlowCapableNodeConnector nodeConnector = portUpdateTranslator.translate(portBld.build(), deviceInfo, null);
commonCheck(nodeConnector);
@Test
public void testTranslate_10() throws Exception {
- Mockito.when(deviceState.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
+ Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures portFeatures =
new org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures(
null, null, null, false, false, true, null, null,
null, false, false, null, null, null, null, null
);
- final FlowCapableNodeConnector nodeConnector = portUpdateTranslator.translate(portBld.build(), deviceState, null);
+ final FlowCapableNodeConnector nodeConnector = portUpdateTranslator.translate(portBld.build(), deviceInfo, null);
commonCheck(nodeConnector);
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
-
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
@Mock
private DeviceContextImpl mockedDeviceContext;
@Mock
+ private DeviceInfo mockedDeviceInfo;
+ @Mock
private DeviceInitializationUtils deviceInitializationUtils;
+ @Mock
+ private DeviceInfo deviceInfo;
@Before
public void setUp() throws Exception {
when(mockConnectionContext.getFeatures()).thenReturn(mockFeatures);
when(mockConnectionContext.getConnectionAdapter()).thenReturn(mockedConnectionAdapter);
when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockConnectionContext);
+ when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
final Capabilities capabilitiesV13 = mock(Capabilities.class);
final CapabilitiesV10 capabilitiesV10 = mock(CapabilitiesV10.class);
GetFeaturesOutput mockedFeatures = mock(GetFeaturesOutput.class);
when(mockedFeatures.getTables()).thenReturn((short) 2);
- when(mockedDeviceState.getFeatures()).thenReturn(mockedFeatures);
- when(mockedDeviceState.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
+ when(mockedDeviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
- when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(DUMMY_NODE_II);
+ when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(DUMMY_NODE_II);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
when(mockedDeviceContext.getMultiMsgCollector(Mockito.any(RequestContext.class))).thenReturn(msgCollector);
when(mockedDeviceContext.oook()).thenReturn(tLibrary);
final GetFeaturesOutput mockedFeatures = mock(GetFeaturesOutput.class);
when(mockedFeatures.getTables()).thenReturn((short) 2);
- when(mockedDeviceState.getFeatures()).thenReturn(mockedFeatures);
+ when(mockConnectionContext.getFeatures()).thenReturn(mockedFeatures);
- when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(DUMMY_NODE_II);
+ when(mockedDeviceInfo.getNodeInstanceIdentifier()).thenReturn(DUMMY_NODE_II);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
final RpcResult<List<MultipartReply>> mockedRpcResult = mock(RpcResult.class);
when(mockedPrimaryConnectionContext.getFeatures()).thenReturn(mockedFeatures);
when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimaryConnectionContext);
final DeviceState mockedDeviceState = mock(DeviceState.class);
- when(mockedDeviceState.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
+ when(mockedDeviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
final MessageTranslator mockedTranslator = mock(MessageTranslator.class);
when(translatorLibrary.lookupTranslator(any(TranslatorKey.class))).thenReturn(mockedTranslator);
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+
import java.math.BigInteger;
import org.junit.Test;
import org.mockito.Matchers;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
import org.opendaylight.yangtools.yang.binding.RpcService;
final ConnectionContext mockedConnectionContext = mock(ConnectionContext.class);
final DeviceState mockedDeviceState = mock(DeviceState.class);
+ final DeviceInfo mockedDeviceInfo = mock(DeviceInfo.class);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
+ when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
final FeaturesReply mockedFeatures = mock(FeaturesReply.class);
when(mockedConnectionContext.getFeatures()).thenReturn(mockedFeatures);
- final GetFeaturesOutput mockedFeaturesOutput = mock(GetFeaturesOutput.class);
- when(mockedDeviceState.getFeatures()).thenReturn(mockedFeaturesOutput);
-
final BigInteger mockedDataPathId = mock(BigInteger.class);
when(mockedFeatures.getDatapathId()).thenReturn(mockedDataPathId);
- when(mockedFeaturesOutput.getDatapathId()).thenReturn(mockedDataPathId);
+ when(mockedDeviceInfo.getDatapathId()).thenReturn(mockedDataPathId);
when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedConnectionContext);
- MdSalRegistrationUtils.registerMasterServices(mockedRpcContext, mockedDeviceContext, OfpRole.BECOMEMASTER);
+
+ final ExtensionConverterProvider extensionConverterProvider = mock(ExtensionConverterProvider.class);
+ MdSalRegistrationUtils.registerMasterServices(mockedRpcContext, mockedDeviceContext, OfpRole.BECOMEMASTER, extensionConverterProvider);
verify(mockedRpcContext, times(NUMBER_OF_RPC_SERVICE_REGISTRATION)).registerRpcServiceImplementation(
Matchers.<Class<RpcService>> any(), any(RpcService.class));
}
package org.opendaylight.openflowplugin.impl.util;
import com.google.common.collect.Lists;
+import java.math.BigInteger;
import junit.framework.TestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.InPortCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.in.port._case.InPortBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketIn;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessageBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.features.reply.PhyPort;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-
-import static org.mockito.Mockito.*;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
/**
* Created by Tomas Slusny on 24.3.2016.
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitchRegistration;
import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationQueueWrapper;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginConfig;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.FutureCallback;
-import java.util.concurrent.ArrayBlockingQueue;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.CheckedFuture;
import org.slf4j.Logger;
private final ListeningExecutorService pool;
- public OfEntityManager( EntityOwnershipService entityOwnershipService ) {
+ private final OpenflowPluginConfig openflowPluginConfig;
+
+ public OfEntityManager(EntityOwnershipService entityOwnershipService, OpenflowPluginConfig ofPluginConfig) {
this.entityOwnershipService = entityOwnershipService;
+ openflowPluginConfig = ofPluginConfig;
ownershipListener = new OpenflowOwnershipListener(this);
entsession = new ConcurrentHashMap<>();
entRegistrationMap = new ConcurrentHashMap<>();
this.dataBroker = dbBroker;
}
+ public void init(){
+ registerEntityOwnershipChangeListener();
+ }
+
+ public void registerEntityOwnershipChangeListener() {
+ if(entityOwnershipService!=null) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("registerEntityOwnershipChangeListener: Registering entity ownership change listener for entitier of type {}", DEVICE_TYPE);
+ }
+ entityOwnershipService.registerListener(DEVICE_TYPE, ownershipListener);
+ }
+ }
+
public void requestOpenflowEntityOwnership(final ModelDrivenSwitch ofSwitch,
final SessionContext context,
final NotificationQueueWrapper wrappedNotification,
MDSwitchMetaData entityMetaData =
new MDSwitchMetaData(ofSwitch,context,wrappedNotification,rpcProviderRegistry);
- if (registeredListener.compareAndSet(false, true)) {
- entityOwnershipService.registerListener(DEVICE_TYPE, ownershipListener);
- }
final Entity entity = new Entity(DEVICE_TYPE, ofSwitch.getNodeId().getValue());
entsession.put(entity, entityMetaData);
final String targetSwitchDPId = sessionContext.getFeatures().getDatapathId().toString();
RolePushTask task = new RolePushTask(newRole, sessionContext);
ListenableFuture<Boolean> rolePushResult = pool.submit(task);
+
final CheckedFuture<Boolean, RolePushException> rolePushResultChecked =
RoleUtil.makeCheckedRuleRequestFxResult(rolePushResult);
Futures.addCallback(rolePushResult, new FutureCallback<Boolean>(){
public void onSuccess(Boolean result){
LOG.info("onDeviceOwnershipChanged: Controller is successfully set as a " +
"MASTER controller for {}", targetSwitchDPId);
- entsession.get(entity).getOfSwitch().sendEmptyTableFeatureRequest();
+ if(!openflowPluginConfig.skipTableFeatures()) {
+ if(LOG.isDebugEnabled()){
+ LOG.debug("Send table feature request for entity {}",entity.getId());
+ }
+ entsession.get(entity).getOfSwitch().sendEmptyTableFeatureRequest();
+ }
sendNodeAddedNotification(entsession.get(entity));
}
// NOOP
}
- private void registerRoutedRPCForSwitch(MDSwitchMetaData entityMetadata) {
+ private static void registerRoutedRPCForSwitch(MDSwitchMetaData entityMetadata) {
// Routed RPC registration is only done when *this* instance is owner of
// the entity.
if(entityMetadata.getOfSwitch().isEntityOwner()) {
if (!entityMetadata.isRPCRegistrationDone.get()) {
entityMetadata.setIsRPCRegistrationDone(true);
- CompositeObjectRegistration<ModelDrivenSwitch> registration =
+ ModelDrivenSwitchRegistration registration =
entityMetadata.getOfSwitch().register(entityMetadata.getRpcProviderRegistry());
entityMetadata.getContext().setProviderRegistration(registration);
}
}
- private void deregisterRoutedRPCForSwitch(MDSwitchMetaData entityMetadata) {
+ private static void deregisterRoutedRPCForSwitch(MDSwitchMetaData entityMetadata) {
- CompositeObjectRegistration<ModelDrivenSwitch> registration = entityMetadata.getContext().getProviderRegistration();
+ ModelDrivenSwitchRegistration registration = entityMetadata.getContext().getProviderRegistration();
if (null != registration) {
registration.close();
entityMetadata.getContext().setProviderRegistration(null);
entityMetadata.getOfSwitch().getNodeId().getValue());
}
- private void sendNodeAddedNotification(MDSwitchMetaData entityMetadata) {
+ private static void sendNodeAddedNotification(MDSwitchMetaData entityMetadata) {
//Node added notification need to be sent irrespective of whether
// *this* instance is owner of the entity or not. Because yang notifications
// are local, and we should maintain the behavior across the application.
*/
package org.opendaylight.openflowplugin.openflow.md.core.sal;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+import java.util.Collection;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.openflowplugin.api.openflow.md.AbstractModelDrivenSwitchRegistration;
import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitchRegistration;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration.CompositeObjectRegistrationBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
}
@Override
- public CompositeObjectRegistration<ModelDrivenSwitch> register(RpcProviderRegistry rpcProviderRegistry) {
- CompositeObjectRegistrationBuilder<ModelDrivenSwitch> builder = CompositeObjectRegistration
- .<ModelDrivenSwitch> builderFor(this);
+ public ModelDrivenSwitchRegistration register(RpcProviderRegistry rpcProviderRegistry) {
+ final Builder<RoutedRpcRegistration<?>> builder = ImmutableList.builder();
final RoutedRpcRegistration<SalFlowService> flowRegistration = rpcProviderRegistry.addRoutedRpcImplementation(SalFlowService.class, this);
flowRegistration.registerPath(NodeContext.class, getIdentifier());
queueStatisticsRegistration.registerPath(NodeContext.class, getIdentifier());
builder.add(queueStatisticsRegistration);
- return builder.build();
+ final Collection<RoutedRpcRegistration<?>> registrations = builder.build();
+ return new AbstractModelDrivenSwitchRegistration(this) {
+ @Override
+ protected void removeRegistration() {
+ for (RoutedRpcRegistration<?> r : registrations) {
+ r.close();
+ }
+ }
+ };
}
/**
--- /dev/null
+/*
+ * Copyright (c) 2016 Ericsson 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.openflowplugin.openflow.md.core.sal;
+
+/**
+ * Created by eshuvka on 5/16/2016.
+ */
+public class OpenflowPluginConfig {
+
+ private final boolean skipTableFeatures;
+
+ private OpenflowPluginConfig (OpenflowPluginConfigBuilder builder){
+ skipTableFeatures = builder.skipTableFeatures();
+ }
+
+ public boolean skipTableFeatures(){
+ return skipTableFeatures;
+ }
+
+ public static OpenflowPluginConfigBuilder builder(){
+ return new OpenflowPluginConfigBuilder();
+ }
+
+ public static class OpenflowPluginConfigBuilder{
+ private boolean skipTableFeatures;
+
+ public boolean skipTableFeatures(){
+ return skipTableFeatures;
+ }
+
+ public void setSkipTableFeatures(boolean skip){
+ skipTableFeatures = skip;
+ }
+
+ public OpenflowPluginConfig build() {return new OpenflowPluginConfig(this);}
+ }
+}
import com.google.common.annotations.VisibleForTesting;
import java.util.Collection;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterManager;
import org.opendaylight.openflowplugin.openflow.md.core.MDController;
import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConverterManagerImpl;
+import org.opendaylight.openflowplugin.openflow.md.core.role.OfEntityManager;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFRoleManager;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
-import org.opendaylight.openflowplugin.openflow.md.core.role.OfEntityManager;
import org.opendaylight.openflowplugin.statistics.MessageSpyCounterImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole;
import org.opendaylight.yangtools.yang.binding.DataContainer;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(OpenflowPluginProvider.class);
+ private static final boolean SKIP_TABLE_FEATURES = false;
+
private Collection<SwitchConnectionProvider> switchConnectionProviders;
private MDController mdController;
private ExtensionConverterManager extensionConverterManager;
private OfpRole role;
+ private Boolean skipTableFeatures;
private OFRoleManager roleManager;
private OfEntityManager entManager;
private RpcProviderRegistry rpcRegistry;
private EntityOwnershipService entityOwnershipService;
+ private OpenflowPluginConfig openflowPluginConfig;
+
+
+
/**
* Initialization of services and msgSpy counter
*/
messageCountProvider = new MessageSpyCounterImpl();
extensionConverterManager = new ExtensionConverterManagerImpl();
roleManager = new OFRoleManager(OFSessionUtil.getSessionManager());
- entManager = new OfEntityManager(entityOwnershipService);
+ openflowPluginConfig = readConfig(skipTableFeatures);
+ entManager = new OfEntityManager(entityOwnershipService,getOpenflowPluginConfig());
entManager.setDataBroker(dataBroker);
+ entManager.init();
LOG.debug("dependencies gathered..");
registrationManager = new SalRegistrationManager();
@Override
public void close() {
LOG.debug("close");
- mdController.stop();
- mdController = null;
- registrationManager.close();
- registrationManager = null;
+
+ if(mdController != null) {
+ mdController.stop();
+ mdController = null;
+ }
+
+ if(registrationManager != null) {
+ registrationManager.close();
+ registrationManager = null;
+ }
}
public MessageCountDumper getMessageCountDumper() {
}
}
+ private OpenflowPluginConfig readConfig(Boolean skipTableFeatures){
+
+ final OpenflowPluginConfig.OpenflowPluginConfigBuilder openflowCfgBuilder = OpenflowPluginConfig.builder();
+
+ if(skipTableFeatures !=null){
+ openflowCfgBuilder.setSkipTableFeatures(skipTableFeatures.booleanValue());
+ } else{
+ LOG.warn("Could not load XML configuration file via ConfigSubsystem! Fallback to default config value(s)");
+ openflowCfgBuilder.setSkipTableFeatures(SKIP_TABLE_FEATURES);
+ }
+
+ return openflowCfgBuilder.build();
+ }
+
public void setDataBroker(DataBroker dataBroker) {
this.dataBroker = dataBroker;
}
this.entityOwnershipService = entityOwnershipService;
}
+ public void setSkipTableFeatures(Boolean skipTableFeatures) {
+ this.skipTableFeatures = skipTableFeatures;
+ }
+
+ @VisibleForTesting
+ public OpenflowPluginConfig getOpenflowPluginConfig() {
+ return openflowPluginConfig;
+ }
+
@VisibleForTesting
protected RpcProviderRegistry getRpcRegistry() {
return rpcRegistry;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitchRegistration;
import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationQueueWrapper;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionListener;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionManager;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
+import org.opendaylight.openflowplugin.openflow.md.core.role.OfEntityManager;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.openflowplugin.openflow.md.core.role.OfEntityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
unregOpenflowEntityOwnership(nodeId);
NodeRemoved nodeRemoved = nodeRemoved(nodeRef);
- CompositeObjectRegistration<ModelDrivenSwitch> registration = context.getProviderRegistration();
+ ModelDrivenSwitchRegistration registration = context.getProviderRegistration();
if (null != registration) {
registration.close();
context.setProviderRegistration(null);
FlowCapableNodeUpdatedBuilder builder2 = new FlowCapableNodeUpdatedBuilder();
try {
builder2.setIpAddress(getIpAddressOf(sw));
+ builder2.setPortNumber(getPortNumberOf(sw));
} catch (Exception e) {
- LOG.warn("IP address of the node {} cannot be obtained.", sw.getNodeId(), e);
+ LOG.warn("IP address/Port Number of the node {} cannot be obtained.", sw.getNodeId(), e);
}
builder2.setSwitchFeatures(swFeaturesUtil.buildSwitchFeatures(features));
builder.addAugmentation(FlowCapableNodeUpdated.class, builder2.build());
throw new IllegalArgumentException("Unsupported IP address type!");
}
+ private static PortNumber getPortNumberOf(ModelDrivenSwitch sw) {
+ SessionContext sessionContext = sw.getSessionContext();
+
+ Preconditions.checkNotNull(sessionContext.getPrimaryConductor(),
+ "primary conductor must not be NULL -> " + sw.getNodeId());
+ Preconditions.checkNotNull(sessionContext.getPrimaryConductor().getConnectionAdapter(),
+ "connection adapter of primary conductor must not be NULL -> " + sw.getNodeId());
+ InetSocketAddress remoteAddress = sessionContext.getPrimaryConductor().getConnectionAdapter()
+ .getRemoteAddress();
+ if (remoteAddress == null) {
+ LOG.warn("Port Number of the node {} cannot be obtained. No connection with switch.", sw.getNodeId());
+ return null;
+ }
+ return resolvePortNumber(remoteAddress.getPort());
+ }
+
+ private static PortNumber resolvePortNumber(int port) {
+ PortNumber portNo = new PortNumber(port);
+ return portNo;
+ }
+
private static NodeRemoved nodeRemoved(final NodeRef nodeRef) {
NodeRemovedBuilder builder = new NodeRemovedBuilder();
builder.setNodeRef(nodeRef);
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
+import java.util.List;
+
+import com.google.common.collect.Lists;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IetfInetUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
* the input is validated via regexps in Ipv6Prefix()
*/
- String [] address = (ipv6Address.getValue()).split("%");
+ Iterable<String> splittedV6Address = Splitter.on("%")
+ .trimResults()
+ .omitEmptyStrings()
+ .split(ipv6Address.getValue());
+ List<String> partsV6Address = Lists.newArrayList(splittedV6Address.iterator());
int colonp;
char ch;
int val;
- char[] src = address[0].toCharArray();
+ char[] src = partsV6Address.get(0).toCharArray();
byte[] dst = new byte[INADDR6SZ];
Preconditions.checkArgument(j != (INADDR6SZ - INADDR4SZ - 1), "Invalid v4 in v6 mapping");
- InetAddress _inet_form = InetAddresses.forString(address[0].substring(curtok, src_length));
+ InetAddress _inet_form = InetAddresses.forString(partsV6Address.get(0).substring(curtok, src_length));
Preconditions.checkArgument(_inet_form instanceof Inet4Address);
System.arraycopy(_inet_form.getAddress(), 0, dst, j, INADDR4SZ);
int mask = 128;
- String [] address = null;
+ Iterable<String> splittedV6Prefix = Splitter.on("/")
+ .trimResults()
+ .omitEmptyStrings()
+ .split(ipv6Prefix.getValue());
+ List<String> partsV6Prefix = Lists.newArrayList(splittedV6Prefix.iterator());
boolean valid = true;
- address = (ipv6Prefix.getValue()).split("/");
try {
- mask = Integer.parseInt(address[1]);
+ mask = Integer.parseInt(partsV6Prefix.get(1));
if (mask > 128) {
valid = false;
}
int val;
- char[] src = address[0].toCharArray();
+ char[] src = partsV6Prefix.get(0).toCharArray();
byte[] dst = new byte[INADDR6SZ + 1];
Preconditions.checkArgument(j != (INADDR6SZ - INADDR4SZ - 1), "Invalid v4 in v6 mapping");
- InetAddress _inet_form = InetAddresses.forString(address[0].substring(curtok, src_length));
+ InetAddress _inet_form = InetAddresses.forString(partsV6Prefix.get(0).substring(curtok, src_length));
Preconditions.checkArgument(_inet_form instanceof Inet4Address);
System.arraycopy(_inet_form.getAddress(), 0, dst, j, INADDR4SZ);
String maskInBits;
// converting byte array to bits
maskInBits = new BigInteger(1, byteMask).toString(2);
+
ArrayList<String> stringMaskArrayList = new ArrayList<String>(Arrays.asList(maskInBits.split("(?!^)")));
for (String string:stringMaskArrayList) {
integerMaskArrayList.add(Integer.parseInt(string));
import org.opendaylight.controller.sal.common.util.Arguments;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
InstanceIdentifier.IdentifiableItem<?, ?> item = Arguments.checkInstanceOf(pathArgument,
InstanceIdentifier.IdentifiableItem.class);
NodeConnectorKey key = Arguments.checkInstanceOf(item.getKey(), NodeConnectorKey.class);
- String[] split = key.getId().getValue().split(":");
- Long port = OpenflowPortsUtil.getPortFromLogicalName(OpenflowVersion.get(ofVersion), split[split.length - 1]);
+ Long port = InventoryDataServiceUtil.portNumberfromNodeConnectorId(
+ OpenflowVersion.get(ofVersion), key.getId());
return new PortNumber(port);
}
}
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
-import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitchRegistration;
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationEnqueuer;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
/**
* @author mirehak
private final AtomicLong xid;
private final Map<Long, PortGrouping> physicalPorts;
private final Map<Long, Boolean> portBandwidth;
- private CompositeObjectRegistration<ModelDrivenSwitch> providerRegistration;
+ private ModelDrivenSwitchRegistration providerRegistration;
private int seed;
private ControllerRole roleOnDevice = ControllerRole.OFPCRROLEEQUAL;
}
@Override
- public void setProviderRegistration(
- CompositeObjectRegistration<ModelDrivenSwitch> providerRegistration) {
- this.providerRegistration = providerRegistration;
+ public void setProviderRegistration(ModelDrivenSwitchRegistration providerRegistration) {
+ this.providerRegistration = providerRegistration;
}
@Override
- public CompositeObjectRegistration<ModelDrivenSwitch> getProviderRegistration() {
+ public ModelDrivenSwitchRegistration getProviderRegistration() {
return providerRegistration;
}
LOG.info("context for invalidation not found");
} else {
synchronized (context) {
- for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context.getAuxiliaryConductors()) {
- invalidateAuxiliary(sessionKey, auxEntry.getKey());
+ if (context.isValid()) {
+ for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context.getAuxiliaryConductors()) {
+ invalidateAuxiliary(sessionKey, auxEntry.getKey());
+ }
+ context.getPrimaryConductor().disconnect();
+ context.setValid(false);
+ removeSessionContext(context);
+ // TODO:: notify listeners
+ } else {
+ LOG.warn("Ignore invalid session context: {}",
+ Arrays.toString(sessionKey.getId()));
}
- context.getPrimaryConductor().disconnect();
- context.setValid(false);
- removeSessionContext(context);
- // TODO:: notify listeners
}
}
}
LOG.info("context for invalidation not found");
} else {
synchronized (sessionContext) {
- for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : sessionContext
- .getAuxiliaryConductors()) {
- invalidateAuxiliary(sessionContext, auxEntry.getKey(), true);
+ if (sessionContext.isValid()) {
+ for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : sessionContext
+ .getAuxiliaryConductors()) {
+ invalidateAuxiliary(sessionContext, auxEntry.getKey(), true);
+ }
+ sessionContext.setValid(false);
+ removeSessionContext(sessionContext);
+ // TODO:: notify listeners
+ } else {
+ LOG.warn("Ignore invalid dead session context: {}",
+ Arrays.toString(
+ sessionContext.getSessionKey().getId()));
}
- sessionContext.setValid(false);
- removeSessionContext(sessionContext);
- // TODO:: notify listeners
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("removing session: {}", Arrays.toString(sessionContext.getSessionKey().getId()));
}
- sessionLot.remove(sessionContext.getSessionKey(), sessionContext);
- sessionNotifier.onSessionRemoved(sessionContext);
+ if (sessionLot.remove(sessionContext.getSessionKey(), sessionContext)) {
+ sessionNotifier.onSessionRemoved(sessionContext);
+ } else {
+ // This should never happen.
+ LOG.warn("Ignore session context that was already removed: {}",
+ Arrays.toString(sessionContext.getSessionKey().getId()));
+ }
}
@Override
import java.math.BigInteger;
import java.util.List;
import java.util.concurrent.ExecutionException;
+
+import com.google.common.base.Splitter;
import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
public abstract class InventoryDataServiceUtil {
public static final String OF_URI_PREFIX = "openflow:";
+ private static final Splitter COLON_SPLITTER = Splitter.on(":");
private static final Logger LOG = LoggerFactory.getLogger(InventoryDataServiceUtil.class);
/*
}
public static String portNoStringfromNodeConnectorID(final String ncID) {
- String[] split = ncID.split(":");
+
+ List<String> splitStringList = COLON_SPLITTER.splitToList(ncID);
// It can happen that token length will be just 1 i.e 2 or CONTROLLER
// If the length is just one then this cannot be the new MD-SAL style node connector Id which
// is of the form openflow:1:3.
- return split[split.length - 1];
+ return splitStringList.get(splitStringList.size()-1);
}
public static Long portNumberfromNodeConnectorId(final OpenflowVersion ofVersion, final String ncId) {
import com.google.common.base.Function;
import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.SettableFuture;
import java.math.BigInteger;
import java.util.concurrent.ExecutionException;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Date;
/**
*
*/
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326;
-import com.google.common.base.MoreObjects;
-import javax.management.ObjectName;
+import java.util.Collection;
+import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
+import org.opendaylight.openflowplugin.api.openflow.statistics.MessageCountDumper;
+import org.opendaylight.openflowplugin.extension.api.ExtensionConverterRegistrator;
import org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider;
+import org.osgi.framework.BundleContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
-*
-*/
+ * @deprecated Replaced by blueprint wiring
+ */
+@Deprecated
public final class ConfigurableOpenFlowProviderModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.AbstractConfigurableOpenFlowProviderModule {
- private OpenflowPluginProvider pluginProvider;
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigurableOpenFlowProviderModule.class);
+
+ private BundleContext bundleContext;
/**
* @param identifier module identifier
}
@Override
- public java.lang.AutoCloseable createInstance() {
- pluginProvider = new OpenflowPluginProvider();
- pluginProvider.setDataBroker(getDataBrokerDependency());
- pluginProvider.setNotificationService(getNotificationServiceDependency());
- pluginProvider.setRpcRegistry(getRpcRegistryDependency());
- pluginProvider.setSwitchConnectionProviders(getOpenflowSwitchConnectionProviderDependency());
- pluginProvider.setEntityOwnershipService(getOwnershipServiceDependency());
- pluginProvider.setRole(getRole());
- pluginProvider.initialization();
- return pluginProvider;
+ public AutoCloseable createInstance() {
+ // The service is provided via blueprint so wait for and return it here for backwards compatibility.
+ String typeFilter = String.format("(type=%s)", getIdentifier().getInstanceName());
+ final WaitingServiceTracker<OpenflowPluginProvider> tracker = WaitingServiceTracker.create(
+ OpenflowPluginProvider.class, bundleContext, typeFilter);
+ final OpenflowPluginProvider actualService = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
+
+ return new OpenflowPluginProvider() {
+ @Override
+ public void close() {
+ // Don't close the actual service as its life cycle is controlled by blueprint.
+ tracker.close();
+ }
+
+ @Override
+ public void initialization() {
+ actualService.initialization();
+ }
+
+ @Override
+ public void setSwitchConnectionProviders(Collection<SwitchConnectionProvider> switchConnectionProvider) {
+ actualService.setSwitchConnectionProviders(switchConnectionProvider);
+ }
+
+ @Override
+ public MessageCountDumper getMessageCountDumper() {
+ return actualService.getMessageCountDumper();
+ }
+
+ @Override
+ public ExtensionConverterRegistrator getExtensionConverterRegistrator() {
+ return actualService.getExtensionConverterRegistrator();
+ }
+
+ @Override
+ public void setRole(OfpRole role) {
+ actualService.setRole(role);
+ }
+
+ @Override
+ public void setSkipTableFeatures(Boolean skipTableFeatures) {
+ actualService.setSkipTableFeatures(skipTableFeatures);
+ }
+
+ @Override
+ public void fireRoleChange(OfpRole newRole) {
+ actualService.fireRoleChange(newRole);
+ }
+
+ @Override
+ public void setDataBroker(DataBroker dataBroker) {
+ actualService.setDataBroker(dataBroker);
+ }
+
+ @Override
+ public void setNotificationService(NotificationProviderService notificationService) {
+ actualService.setNotificationService(notificationService);
+ }
+
+ @Override
+ public void setRpcRegistry(RpcProviderRegistry rpcRegistry) {
+ actualService.setRpcRegistry(rpcRegistry);
+ }
+
+ @Override
+ public void setEntityOwnershipService(EntityOwnershipService entityOwnershipService) {
+ actualService.setEntityOwnershipService(entityOwnershipService);
+ }
+ };
}
- @Override
- public boolean canReuseInstance(
- AbstractConfigurableOpenFlowProviderModule oldModule) {
- // we can reuse if only the role field changed
- boolean noChangeExceptRole = true;
- noChangeExceptRole &= dependencyResolver.canReuseDependency(
- getDataBroker(), dataBrokerJmxAttribute);
- noChangeExceptRole &= dependencyResolver.canReuseDependency(
- getNotificationService(), notificationServiceJmxAttribute);
- noChangeExceptRole &= dependencyResolver.canReuseDependency(
- getRpcRegistry(), rpcRegistryJmxAttribute);
-
- for (ObjectName ofSwitchProvider : getOpenflowSwitchConnectionProvider()) {
- noChangeExceptRole &= dependencyResolver.canReuseDependency(
- ofSwitchProvider, openflowSwitchConnectionProviderJmxAttribute);
- }
- return noChangeExceptRole;
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
}
@Override
- public AutoCloseable reuseInstance(AutoCloseable oldInstance) {
- OpenflowPluginProvider recycled = (OpenflowPluginProvider) super.reuseInstance(oldInstance);
- // change role if different
- recycled.fireRoleChange(MoreObjects.firstNonNull(getRole(), getRole()));
-
- return recycled;
+ public boolean canReuseInstance(AbstractConfigurableOpenFlowProviderModule oldModule) {
+ return true;
}
+
}
*/
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.osgi.framework.BundleContext;
/**
- * the only purpose of this overwritings is to deliver bundleContext from osgi to module
+ * @deprecated Replaced by blueprint wiring
*/
-public class ConfigurableOpenFlowProviderModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.AbstractConfigurableOpenFlowProviderModuleFactory
-{
- // nothing to override
+@Deprecated
+public class ConfigurableOpenFlowProviderModuleFactory extends AbstractConfigurableOpenFlowProviderModuleFactory {
+ @Override
+ public ConfigurableOpenFlowProviderModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
+ ConfigurableOpenFlowProviderModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) {
+ ConfigurableOpenFlowProviderModule module = super.instantiateModule(instanceName, dependencyResolver, oldModule,
+ oldInstance, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+ @Override
+ public ConfigurableOpenFlowProviderModule instantiateModule(String instanceName, DependencyResolver dependencyResolver,
+ BundleContext bundleContext) {
+ ConfigurableOpenFlowProviderModule module = super.instantiateModule(instanceName, dependencyResolver, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
}
type ofp-role;
default "NOCHANGE";
}
+
+ leaf skip-table-features {
+ description "Ability to skip pulling and storing of large table features. These features are still
+ available via rpc, so if use set it to true, it won't store table feature data in DataStore.";
+ type boolean;
+ default "false";
+ }
}
case msg-spy-service-impl {
identity openflow-provider{
base config:service-type;
config:java-class "org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider";
+ config:disable-osgi-service-registration;
}
}
\ No newline at end of file
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.openflowplugin.openflow.md.core.role.OfEntityManager;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
/**
* simple NPE smoke test
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListeningExecutorService;
import java.math.BigInteger;
-import java.util.Collections;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.md.AbstractModelDrivenSwitchRegistration;
import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitchRegistration;
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationEnqueuer;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
+import org.opendaylight.openflowplugin.openflow.md.core.role.OfEntityManager;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContextOFImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
-import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.openflowplugin.openflow.md.core.role.OfEntityManager;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
/**
* Created by Martin Bobak mbobak@cisco.com on 8/26/14.
private ModelDrivenSwitch mdSwitchOF13;
-
- CompositeObjectRegistration<ModelDrivenSwitch> registration;
-
+ ModelDrivenSwitchRegistration registration;
@Before
public void setUp() {
context.setFeatures(features);
context.setNotificationEnqueuer(notificationEnqueuer);
- OfEntityManager entManager = new OfEntityManager(entityOwnershipService);
+ OfEntityManager entManager = new OfEntityManager(entityOwnershipService,getConfig());
mdSwitchOF13 = new ModelDrivenSwitchImpl(null, null, context);
- registration = new CompositeObjectRegistration<>(mdSwitchOF13, Collections.<Registration>emptyList());
+ registration = new AbstractModelDrivenSwitchRegistration(mdSwitchOF13) {
+ @Override
+ protected void removeRegistration() {
+ // no-op
+ }
+ };
context.setProviderRegistration(registration);
UpdateFlowOutputBuilder updateFlowOutput = new UpdateFlowOutputBuilder();
SwitchSessionKeyOF switchSessionKeyOF = new SwitchSessionKeyOF();
salRegistrationManager.onSessionAdded(switchSessionKeyOF, context);
}
+
+ public OpenflowPluginConfig getConfig(){
+ OpenflowPluginConfig.OpenflowPluginConfigBuilder cfgBuilder =
+ new OpenflowPluginConfig.OpenflowPluginConfigBuilder();
+ cfgBuilder.setSkipTableFeatures(true);
+ return cfgBuilder.build();
+
+ }
}
import java.math.BigInteger;\r
import java.util.ArrayList;\r
import java.util.List;\r
-\r
import org.junit.Assert;\r
import org.junit.Test;\r
import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instruction.grouping.instruction.choice.WriteMetadataCase;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;\r
\r
/**\r
import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;\r
import org.opendaylight.openflowplugin.api.OFConstants;\r
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;\r
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;\r
import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;\r
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;\r
*/\r
private static PortNumber getPortNumber(final NodeConnectorKey nConKey,\r
final Short ofVersion) {\r
- String[] split = nConKey.getId().getValue().split(":");\r
- Long port = OpenflowPortsUtil.getPortFromLogicalName(\r
- OpenflowVersion.get(ofVersion), split[split.length - 1]);\r
+ Long port = InventoryDataServiceUtil.portNumberfromNodeConnectorId(\r
+ OpenflowVersion.get(ofVersion), nConKey.getId());\r
return new PortNumber(port);\r
}\r
\r
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandler;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitchRegistration;
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.ErrorHandler;
import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationEnqueuer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
private Map<SwitchConnectionDistinguisher, ConnectionConductor> map;
private IMessageDispatchService messageService;
private boolean isValid = true;
- private CompositeObjectRegistration<ModelDrivenSwitch> registration;
+ private ModelDrivenSwitchRegistration registration;
private int seed;
private SwitchSessionKeyOF sessionKey;
}
@Override
- public CompositeObjectRegistration<ModelDrivenSwitch> getProviderRegistration() {
+ public ModelDrivenSwitchRegistration getProviderRegistration() {
return registration;
}
@Override
- public void setProviderRegistration(
- CompositeObjectRegistration<ModelDrivenSwitch> registration) {
+ public void setProviderRegistration(ModelDrivenSwitchRegistration registration) {
this.registration = registration;
}
import com.google.common.util.concurrent.Futures;
import java.math.BigInteger;
import java.util.Collections;
-import java.util.List;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
portNumber = new PortNumberUni(OutputPortValues.FLOOD.toString());
Assert.assertEquals("FLOOD", OpenflowPortsUtil.portNumberToString(portNumber));
- try {
- portNumber = new PortNumberUni((String) null);
- Assert.fail("NPE was expected - due to value type");
- } catch (Exception e) {
- // expected
- Assert.assertEquals(NullPointerException.class, e.getClass());
- }
+
+ portNumber = new PortNumberUni((String) null);
+ Assert.assertNotNull(portNumber);
+
}
}
<openflowjava.version>0.8.0-SNAPSHOT</openflowjava.version>
<openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
<sal.api.version>0.11.0-SNAPSHOT</sal.api.version>
- <jmxGeneratorPath>src/main/yang-gen-config</jmxGeneratorPath>
- <salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
+ <jmxGeneratorPath>target/generated-sources/config</jmxGeneratorPath>
+ <salGeneratorPath>target/generated-sources/sal</salGeneratorPath>
<exi.nagasena.version>0000.0002.0053.0</exi.nagasena.version>
<controller.distribution.version>0.4.0-SNAPSHOT</controller.distribution.version>
<ignore/>
</action>
</pluginExecution>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <versionRange>[0.5,)</versionRange>
- <goals>
- <goal>generate-sources</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <execute/>
- </action>
- </pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.groovy.maven</groupId>
<module>extension</module>
<module>distribution/karaf</module>
<module>openflowplugin-controller-config</module>
+ <module>openflowplugin-blueprint-config-he</module>
+ <module>openflowplugin-blueprint-config</module>
<!--
<module>openflowplugin-it</module>
-->
<module>drop-test-karaf</module>
<module>test-common</module>
<module>features</module>
- <module>features-li</module>
+ <module>features-he</module>
<module>samples/sample-consumer</module>
<module>samples/learning-switch</module>
<module>applications</module>
import com.google.common.util.concurrent.Futures;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
import org.osgi.framework.BundleContext;
public class OpenflowpluginGroupTestCommandProvider implements CommandProvider {
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration.CompositeObjectRegistrationBuilder;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
/**
* @param ctx
- * @return {@link CompositeObjectRegistrationBuilder #toInstance()}
+ * @return {@link ObjectRegistration}
*/
- public CompositeObjectRegistration<OpenflowpluginGroupTestServiceProvider> register(
+ public ObjectRegistration<OpenflowpluginGroupTestServiceProvider> register(
final ProviderContext ctx) {
- CompositeObjectRegistrationBuilder<OpenflowpluginGroupTestServiceProvider> builder = CompositeObjectRegistration
- .<OpenflowpluginGroupTestServiceProvider> builderFor(this);
-
RoutedRpcRegistration<SalGroupService> addRoutedRpcImplementation = ctx
.<SalGroupService> addRoutedRpcImplementation(
SalGroupService.class, this);
groupRegistration.registerPath(NodeContext.class, instance);
RoutedRpcRegistration<SalGroupService> groupRegistration1 = this
.getGroupRegistration();
- builder.add(groupRegistration1);
- return builder.build();
+ return new AbstractObjectRegistration<OpenflowpluginGroupTestServiceProvider>(this) {
+ @Override
+ protected void removeRegistration() {
+ groupRegistration1.close();
+ }
+ };
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutput;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration.CompositeObjectRegistrationBuilder;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
/**
* @param ctx
- * @return {@link CompositeObjectRegistrationBuilder #toInstance()}
+ * @return {@link ObjectRegistration}
*/
- public CompositeObjectRegistration<OpenflowpluginMeterTestServiceProvider> register(
+ public ObjectRegistration<OpenflowpluginMeterTestServiceProvider> register(
final ProviderContext ctx) {
- CompositeObjectRegistrationBuilder<OpenflowpluginMeterTestServiceProvider> builder = CompositeObjectRegistration
- .<OpenflowpluginMeterTestServiceProvider> builderFor(this);
RoutedRpcRegistration<SalMeterService> addRoutedRpcImplementation = ctx
.<SalMeterService> addRoutedRpcImplementation(
RoutedRpcRegistration<SalMeterService> meterRegistration1 = this
.getMeterRegistration();
- builder.add(meterRegistration1);
+ return new AbstractObjectRegistration<OpenflowpluginMeterTestServiceProvider>(this) {
- return builder.build();
+ @Override
+ protected void removeRegistration() {
+ meterRegistration1.close();
+ }
+ };
}
}
import java.util.Iterator;
import java.util.List;
-
import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-
public class OpenflowpluginStatsTestCommandProvider implements CommandProvider {
private static final Logger LOG = LoggerFactory
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration.CompositeObjectRegistrationBuilder;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
/**
* @param ctx
- * @return {@link CompositeObjectRegistrationBuilder #toInstance()}
+ * @return {@link ObjectRegistration}
*/
- public CompositeObjectRegistration<OpenflowpluginTableFeaturesTestServiceProvider> register(
+ public ObjectRegistration<OpenflowpluginTableFeaturesTestServiceProvider> register(
final ProviderContext ctx) {
- CompositeObjectRegistrationBuilder<OpenflowpluginTableFeaturesTestServiceProvider> builder = CompositeObjectRegistration
- .<OpenflowpluginTableFeaturesTestServiceProvider> builderFor(this);
-
RoutedRpcRegistration<SalTableService> addRoutedRpcImplementation = ctx
.<SalTableService> addRoutedRpcImplementation(
SalTableService.class, this);
RoutedRpcRegistration<SalTableService> tableRegistration1 = this
.getTableRegistration();
- builder.add(tableRegistration1);
-
- return builder.build();
+ return new AbstractObjectRegistration<OpenflowpluginTableFeaturesTestServiceProvider>(this) {
+ @Override
+ protected void removeRegistration() {
+ tableRegistration1.close();
+ }
+ };
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration.CompositeObjectRegistrationBuilder;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
/**
* @param ctx
- * @return {@link CompositeObjectRegistrationBuilder #toInstance()}
+ * @return {@link ObjectRegistration}
*/
- public CompositeObjectRegistration<OpenflowpluginTestServiceProvider> register(
+ public ObjectRegistration<OpenflowpluginTestServiceProvider> register(
final ProviderContext ctx) {
- CompositeObjectRegistrationBuilder<OpenflowpluginTestServiceProvider> builder = CompositeObjectRegistration
- .<OpenflowpluginTestServiceProvider> builderFor(this);
-
RoutedRpcRegistration<SalFlowService> addRoutedRpcImplementation = ctx
.<SalFlowService> addRoutedRpcImplementation(
SalFlowService.class, this);
RoutedRpcRegistration<SalFlowService> flowRegistration2 = getFlowRegistration();
- builder.add(flowRegistration2);
-
- return builder.build();
+ return new AbstractObjectRegistration<OpenflowpluginTestServiceProvider>(this) {
+ @Override
+ protected void removeRegistration() {
+ flowRegistration2.close();
+ }
+ };
}
}
+++ /dev/null
-*.pyc
-/.pydevproject
-*.log
-.tox/