From: Tomas Slusny Date: Mon, 19 Jun 2017 12:45:35 +0000 (+0200) Subject: Encapsulate OpenFlowPlugin configuration X-Git-Tag: release/nitrogen~49 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=bb5487ecc9d866af16d2f80e3fae7e35b9a8bf2e;p=openflowplugin.git Encapsulate OpenFlowPlugin configuration - Stop sending configuration to OpenFlow managers in long constructors and send just aggregated configuration in one class - Add ability to register configuration listener to configuration service - Separate configuration service from OpenFlowPluginProviderImpl - Fix FRM configuration breaking OpenFlowPlugin configuration by trying to load configuration from openflowplugin.cfg directly, what is only accesible to main OpenFlowPlugin project by creating configuration service and passing it to FRM - Add missing 'disable-reconciliation' flag to FRM yang config, and use default values from YANG file for FRM configuration Resolves: bug 8705 Change-Id: I791925bb1964c9eb5a9f1db77fcc25f6425f053f Signed-off-by: Tomas Slusny --- diff --git a/applications/forwardingrules-manager/pom.xml b/applications/forwardingrules-manager/pom.xml index 4dbbe7c5e0..a97e19fbb8 100644 --- a/applications/forwardingrules-manager/pom.xml +++ b/applications/forwardingrules-manager/pom.xml @@ -11,10 +11,6 @@ bundle - - junit - junit - org.opendaylight.controller sal-binding-api @@ -43,7 +39,15 @@ org.opendaylight.mdsal mdsal-singleton-common-api - + + org.opendaylight.openflowplugin + openflowplugin-api + + + junit + junit + test + org.mockito mockito-core @@ -75,7 +79,6 @@ - scm:git:ssh://git.opendaylight.org:29418/openflowplugin.git scm:git:ssh://git.opendaylight.org:29418/openflowplugin.git diff --git a/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/ForwardingRulesManager.java b/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/ForwardingRulesManager.java index 0dcd3aa176..2bfd84037f 100644 --- a/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/ForwardingRulesManager.java +++ b/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/ForwardingRulesManager.java @@ -9,6 +9,7 @@ package org.opendaylight.openflowplugin.applications.frm; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationListener; 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; @@ -17,7 +18,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalF 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; @@ -29,7 +29,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; * * @author Vaclav Demcak */ -public interface ForwardingRulesManager extends AutoCloseable { +public interface ForwardingRulesManager extends ConfigurationListener, AutoCloseable { void start(); diff --git a/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/ForwardingRulesProperty.java b/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/ForwardingRulesProperty.java new file mode 100644 index 0000000000..8fab3c0934 --- /dev/null +++ b/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/ForwardingRulesProperty.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. 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; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; + +public enum ForwardingRulesProperty { + DISABLE_RECONCILIATION, + STALE_MARKING_ENABLED, + RECONCILIATION_RETRY_COUNT; + + + private static final Map KEY_VALUE_MAP; + + /** + * Get property type from property key + * + * @param key the property key + * @return the property type + */ + public static ForwardingRulesProperty forValue(final String key) { + return KEY_VALUE_MAP.get(key); + } + + static { + final ForwardingRulesProperty[] values = values(); + final ImmutableMap.Builder builder = ImmutableMap.builder(); + + for (final ForwardingRulesProperty value : values) { + builder.put(value.toString(), value); + } + + KEY_VALUE_MAP = builder.build(); + } + + /** + * Converts enum name to property key + * + * @return the property key + */ + @Override + public String toString() { + return this.name().toLowerCase().replace('_', '-'); + } +} diff --git a/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/impl/ForwardingRulesManagerImpl.java b/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/impl/ForwardingRulesManagerImpl.java index 9bfa943639..b98c271093 100644 --- a/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/impl/ForwardingRulesManagerImpl.java +++ b/applications/forwardingrules-manager/src/main/java/org/opendaylight/openflowplugin/applications/frm/impl/ForwardingRulesManagerImpl.java @@ -9,10 +9,10 @@ package org.opendaylight.openflowplugin.applications.frm.impl; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.CheckedFuture; import java.util.Objects; +import java.util.Optional; import java.util.concurrent.atomic.AtomicLong; import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.binding.api.DataBroker; @@ -22,9 +22,11 @@ import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.sal.binding.api.NotificationProviderService; import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService; import org.opendaylight.openflowplugin.applications.frm.FlowNodeReconciliation; import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesCommiter; import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager; +import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesProperty; 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; @@ -60,13 +62,9 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager { private final SalGroupService salGroupService; private final SalMeterService salMeterService; private final SalTableService salTableService; - private final ForwardingRulesManagerConfig forwardingRulesManagerConfig; private final ClusterSingletonServiceProvider clusterSingletonServiceProvider; private final NotificationProviderService notificationService; - private final boolean disableReconciliation; - private final boolean staleMarkingEnabled; - private final int reconciliationRetryCount; - + private final AutoCloseable configurationServiceRegistration; private ForwardingRulesCommiter flowListener; private ForwardingRulesCommiter groupListener; private ForwardingRulesCommiter meterListener; @@ -74,20 +72,25 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager { private FlowNodeReconciliation nodeListener; private FlowNodeConnectorInventoryTranslatorImpl flowNodeConnectorInventoryTranslatorImpl; private DeviceMastershipManager deviceMastershipManager; + private boolean disableReconciliation; + private boolean staleMarkingEnabled; + private int reconciliationRetryCount; public ForwardingRulesManagerImpl(final DataBroker dataBroker, final RpcConsumerRegistry rpcRegistry, final ForwardingRulesManagerConfig config, final ClusterSingletonServiceProvider clusterSingletonService, final NotificationProviderService notificationService, - final boolean disableReconciliation, - final boolean staleMarkingEnabled, - final int reconciliationRetryCount) { + final ConfigurationService configurationService) { + disableReconciliation = config.isDisableReconciliation(); + staleMarkingEnabled = config.isStaleMarkingEnabled(); + reconciliationRetryCount = config.getReconciliationRetryCount(); + + this.configurationServiceRegistration = configurationService.registerListener(this); this.dataService = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!"); - this.forwardingRulesManagerConfig = Preconditions.checkNotNull(config, "Configuration for FRM cannot be null"); this.clusterSingletonServiceProvider = Preconditions.checkNotNull(clusterSingletonService, "ClusterSingletonService provider can not be null"); - this.notificationService = Preconditions.checkNotNull(notificationService, "Notification publisher service is" + + this.notificationService = Preconditions.checkNotNull(notificationService, "Notification publisher configurationService is" + " not available"); Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !"); @@ -100,10 +103,6 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager { "RPC SalMeterService not found."); this.salTableService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalTableService.class), "RPC SalTableService not found."); - - this.disableReconciliation = disableReconciliation; - this.staleMarkingEnabled = staleMarkingEnabled; - this.reconciliationRetryCount = reconciliationRetryCount; } @Override @@ -124,6 +123,8 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager { @Override public void close() throws Exception { + configurationServiceRegistration.close(); + if (this.flowListener != null) { this.flowListener.close(); this.flowListener = null; @@ -169,10 +170,9 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager { boolean result = false; InstanceIdentifier nodeIid = ident.firstIdentifierOf(Node.class); final ReadOnlyTransaction transaction = dataService.newReadOnlyTransaction(); - Optional optionalDataObject; - CheckedFuture, ReadFailedException> future = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid); + CheckedFuture, ReadFailedException> future = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid); try { - optionalDataObject = future.checkedGet(); + com.google.common.base.Optional optionalDataObject = future.checkedGet(); if (optionalDataObject.isPresent()) { result = true; } else { @@ -229,17 +229,17 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager { @Override public boolean isReconciliationDisabled() { - return this.disableReconciliation; + return disableReconciliation; } @Override public boolean isStaleMarkingEnabled() { - return this.staleMarkingEnabled; + return staleMarkingEnabled; } @Override public int getReconciliationRetryCount() { - return this.reconciliationRetryCount; + return reconciliationRetryCount; } @Override @@ -256,5 +256,21 @@ public class ForwardingRulesManagerImpl implements ForwardingRulesManager { public void setDeviceMastershipManager(final DeviceMastershipManager deviceMastershipManager) { this.deviceMastershipManager = deviceMastershipManager; } -} + @Override + public void onPropertyChanged(@Nonnull final String propertyName, @Nonnull final String propertyValue) { + Optional.ofNullable(ForwardingRulesProperty.forValue(propertyName)).ifPresent(forwardingRulesProperty -> { + switch (forwardingRulesProperty) { + case DISABLE_RECONCILIATION: + disableReconciliation = Boolean.valueOf(propertyValue); + break; + case STALE_MARKING_ENABLED: + staleMarkingEnabled = Boolean.valueOf(propertyValue); + break; + case RECONCILIATION_RETRY_COUNT: + reconciliationRetryCount = Integer.valueOf(propertyValue); + break; + } + }); + } +} diff --git a/applications/forwardingrules-manager/src/main/resources/org/opendaylight/blueprint/forwardingrules-manager.xml b/applications/forwardingrules-manager/src/main/resources/org/opendaylight/blueprint/forwardingrules-manager.xml index 34a6dc8f45..951d27f74d 100644 --- a/applications/forwardingrules-manager/src/main/resources/org/opendaylight/blueprint/forwardingrules-manager.xml +++ b/applications/forwardingrules-manager/src/main/resources/org/opendaylight/blueprint/forwardingrules-manager.xml @@ -8,23 +8,11 @@ + - - - - - - - - - - - @@ -32,9 +20,6 @@ - - - - + - \ No newline at end of file + diff --git a/applications/forwardingrules-manager/src/main/yang/forwardingrules-manager-config.yang b/applications/forwardingrules-manager/src/main/yang/forwardingrules-manager-config.yang index f2772f8a88..62899dba77 100644 --- a/applications/forwardingrules-manager/src/main/yang/forwardingrules-manager-config.yang +++ b/applications/forwardingrules-manager/src/main/yang/forwardingrules-manager-config.yang @@ -12,6 +12,11 @@ module forwarding-rules-manager-config { } container forwarding-rules-manager-config { + leaf disable-reconciliation { + type boolean; + default false; + } + leaf stale-marking-enabled { type boolean; default false; @@ -22,4 +27,4 @@ module forwarding-rules-manager-config { default 5; } } -} \ No newline at end of file +} diff --git a/applications/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java b/applications/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java index 5246750de9..89644a7a90 100644 --- a/applications/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java +++ b/applications/forwardingrules-manager/src/test/java/test/mock/FlowListenerTest.java @@ -74,7 +74,9 @@ public class FlowListenerTest extends FRMTest { rpcProviderRegistryMock, getConfig(), clusterSingletonService, - notificationService, false, false, 5); + notificationService, + getConfigurationService()); + forwardingRulesManager.start(); // TODO consider tests rewrite (added because of complicated access) forwardingRulesManager.setDeviceMastershipManager(deviceMastershipManager); diff --git a/applications/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java b/applications/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java index 7c990531d3..924ece1b20 100644 --- a/applications/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java +++ b/applications/forwardingrules-manager/src/test/java/test/mock/GroupListenerTest.java @@ -64,7 +64,9 @@ public class GroupListenerTest extends FRMTest { rpcProviderRegistryMock, getConfig(), clusterSingletonService, - notificationService, false, false, 5); + notificationService, + getConfigurationService()); + forwardingRulesManager.start(); // TODO consider tests rewrite (added because of complicated access) forwardingRulesManager.setDeviceMastershipManager(deviceMastershipManager); diff --git a/applications/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java b/applications/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java index 6fca053ef6..eeae3f0828 100644 --- a/applications/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java +++ b/applications/forwardingrules-manager/src/test/java/test/mock/MeterListenerTest.java @@ -64,7 +64,9 @@ public class MeterListenerTest extends FRMTest { rpcProviderRegistryMock, getConfig(), clusterSingletonService, - notificationService, false, false, 5); + notificationService, + getConfigurationService()); + forwardingRulesManager.start(); // TODO consider tests rewrite (added because of complicated access) forwardingRulesManager.setDeviceMastershipManager(deviceMastershipManager); diff --git a/applications/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java b/applications/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java index cfae719021..c362ad2583 100644 --- a/applications/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java +++ b/applications/forwardingrules-manager/src/test/java/test/mock/NodeListenerTest.java @@ -46,7 +46,9 @@ public class NodeListenerTest extends FRMTest { rpcProviderRegistryMock, getConfig(), clusterSingletonService, - notificationService, false ,false ,5); + notificationService, + getConfigurationService()); + forwardingRulesManager.start(); } diff --git a/applications/forwardingrules-manager/src/test/java/test/mock/TableFeaturesListenerTest.java b/applications/forwardingrules-manager/src/test/java/test/mock/TableFeaturesListenerTest.java index 52e0b85169..17d64624bc 100644 --- a/applications/forwardingrules-manager/src/test/java/test/mock/TableFeaturesListenerTest.java +++ b/applications/forwardingrules-manager/src/test/java/test/mock/TableFeaturesListenerTest.java @@ -59,7 +59,9 @@ public class TableFeaturesListenerTest extends FRMTest { rpcProviderRegistryMock, getConfig(), clusterSingletonService, - notificationService, false, false , 5); + notificationService, + getConfigurationService()); + forwardingRulesManager.start(); // TODO consider tests rewrite (added because of complicated access) forwardingRulesManager.setDeviceMastershipManager(deviceMastershipManager); diff --git a/applications/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java b/applications/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java index 321722b8a5..8f52415cb1 100644 --- a/applications/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java +++ b/applications/forwardingrules-manager/src/test/java/test/mock/util/FRMTest.java @@ -9,9 +9,11 @@ package test.mock.util; import java.util.Collections; import java.util.concurrent.ExecutionException; +import org.mockito.Mockito; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService; 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; @@ -63,11 +65,30 @@ public abstract class FRMTest extends AbstractDataBrokerTest { assertCommit(writeTx.submit()); } - public ForwardingRulesManagerConfig getConfig(){ + public ForwardingRulesManagerConfig getConfig() { ForwardingRulesManagerConfigBuilder cfgBuilder = new ForwardingRulesManagerConfigBuilder(); + cfgBuilder.setDisableReconciliation(false); cfgBuilder.setStaleMarkingEnabled(false); cfgBuilder.setReconciliationRetryCount(0); return cfgBuilder.build(); + } + + public ConfigurationService getConfigurationService() { + final ConfigurationService configurationService = Mockito.mock(ConfigurationService.class); + final ForwardingRulesManagerConfig config = getConfig(); + + Mockito.when(configurationService.registerListener(Mockito.any())).thenReturn(() -> {}); + + Mockito.when(configurationService.getProperty(Mockito.eq("disable-reconciliation"), Mockito.any())) + .thenReturn(config.isDisableReconciliation()); + Mockito.when(configurationService.getProperty(Mockito.eq("stale-marking-enabled"), Mockito.any())) + .thenReturn(config.isStaleMarkingEnabled()); + + Mockito.when(configurationService.getProperty(Mockito.eq("reconciliation-retry-count"), Mockito.any())) + .thenReturn(config.getReconciliationRetryCount()); + + return configurationService; } + } diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginConfigurationService.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginConfigurationService.java deleted file mode 100644 index 1f7adb61fd..0000000000 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginConfigurationService.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2017 Pantheon Technologies s.r.o. 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 com.google.common.collect.ImmutableMap; -import java.util.Map; -import javax.annotation.Nonnull; - -/** - * Manages OpenFlowPlugin configuration. - */ -public interface OpenFlowPluginConfigurationService { - - /** - * Enum of property keys. All keys from OpenFlowPlugin configuration file are parsed to this enum. - * Each enum value represents one working configuration key in format - * ENUM.name().toLowerCase().replace('_', '-'), so for example PropertyType.IS_STATISTICS_POLLING_ON - * represents 'is-statistics-polling-on' configuration key. - */ - enum PropertyType { - /** - * Is statistics polling on property type. - */ - IS_STATISTICS_POLLING_ON, - /** - * Barrier count limit property type. - */ - BARRIER_COUNT_LIMIT, - /** - * Barrier interval timeout limit property type. - */ - BARRIER_INTERVAL_TIMEOUT_LIMIT, - /** - * Echo reply timeout property type. - */ - ECHO_REPLY_TIMEOUT, - /** - * Enable flow removed notification property type. - */ - ENABLE_FLOW_REMOVED_NOTIFICATION, - /** - * Skip table features property type. - */ - SKIP_TABLE_FEATURES, - /** - * Basic timer delay property type. - */ - BASIC_TIMER_DELAY, - /** - * Maximum timer delay property type. - */ - MAXIMUM_TIMER_DELAY, - /** - * Switch features mandatory property type. - */ - SWITCH_FEATURES_MANDATORY, - /** - * Is statistics rpc enabled property type. - */ - @Deprecated - IS_STATISTICS_RPC_ENABLED, - /** - * Use single layer serialization property type. - */ - USE_SINGLE_LAYER_SERIALIZATION, - /** - * Rpc requests quota property type. - */ - RPC_REQUESTS_QUOTA, - /** - * Global notification quota property type. - */ - GLOBAL_NOTIFICATION_QUOTA, - /** - * Thread pool min threads property type. - */ - THREAD_POOL_MIN_THREADS, - /** - * Thread pool max threads property type. - */ - THREAD_POOL_MAX_THREADS, - /** - * Thread pool timeout property type. - */ - THREAD_POOL_TIMEOUT; - - private static final Map KEY_VALUE_MAP; - - /** - * Get property type from property key. - * - * @param key the property key - * @return the property type - */ - public static PropertyType forValue(String key) { - return KEY_VALUE_MAP.get(key); - } - - static { - final PropertyType[] values = values(); - final ImmutableMap.Builder builder = ImmutableMap.builder(); - - for (final PropertyType value : values) { - builder.put(value.toString(), value); - } - - KEY_VALUE_MAP = builder.build(); - } - - /** - * Converts enum name to property key. - * - * @return the property key - */ - @Override - public String toString() { - return this.name().toLowerCase().replace('_', '-'); - } - - } - - /** - * Parses key-value pairs of properties read from OpenFlowPlugin configuration file and processes them. - * - * @param properties properties - */ - void update(@Nonnull Map properties); - - /** - * Parse and process single property key-value pair. - * - * @see org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginConfigurationService.PropertyType - * @param key property type - * @param value property value - */ - void updateProperty(@Nonnull PropertyType key, @Nonnull Object value); - -} diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginProviderFactory.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginProviderFactory.java index 8a0bf197da..ef5aedec45 100644 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginProviderFactory.java +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/OpenFlowPluginProviderFactory.java @@ -14,19 +14,17 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; 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; -import org.osgi.framework.BundleContext; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService; /** * Factory for creating OpenFlowPluginProvider instances. */ public interface OpenFlowPluginProviderFactory { - OpenFlowPluginProvider newInstance(OpenflowProviderConfig providerConfig, + OpenFlowPluginProvider newInstance(ConfigurationService configurationService, DataBroker dataBroker, RpcProviderRegistry rpcRegistry, NotificationPublishService notificationPublishService, EntityOwnershipService entityOwnershipService, List switchConnectionProviders, - ClusterSingletonServiceProvider singletonServiceProvider, - BundleContext bundleContext); + ClusterSingletonServiceProvider singletonServiceProvider); } diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationListener.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationListener.java new file mode 100644 index 0000000000..a03a59729c --- /dev/null +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationListener.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.configuration; + +import javax.annotation.Nonnull; + +/** + * Listens for changes in OpenFlowPlugin configuration. + */ +public interface ConfigurationListener { + + /** + * Method invoked on configuration property change. + * + * @param propertyName the property name + * @param propertyValue the property value + */ + void onPropertyChanged(@Nonnull String propertyName, @Nonnull String propertyValue); + +} diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationProperty.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationProperty.java new file mode 100644 index 0000000000..da80b861f0 --- /dev/null +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationProperty.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.configuration; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; + +/** + * Enum of property keys. All keys from OpenFlowPlugin configuration file are parsed to this enum. + * Each enum value represents one working configuration key in format + * ENUM.name().toLowerCase().replace('_', '-'), so for example ConfigurationProperty.IS_STATISTICS_POLLING_ON + * represents 'is-statistics-polling-on' configuration key. + */ +public enum ConfigurationProperty { + /** + * Is statistics polling on property type. + */ + IS_STATISTICS_POLLING_ON, + /** + * Barrier count limit property type. + */ + BARRIER_COUNT_LIMIT, + /** + * Barrier interval timeout limit property type. + */ + BARRIER_INTERVAL_TIMEOUT_LIMIT, + /** + * Echo reply timeout property type. + */ + ECHO_REPLY_TIMEOUT, + /** + * Enable flow removed notification property type. + */ + ENABLE_FLOW_REMOVED_NOTIFICATION, + /** + * Skip table features property type. + */ + SKIP_TABLE_FEATURES, + /** + * Basic timer delay property type. + */ + BASIC_TIMER_DELAY, + /** + * Maximum timer delay property type. + */ + MAXIMUM_TIMER_DELAY, + /** + * Switch features mandatory property type. + */ + SWITCH_FEATURES_MANDATORY, + /** + * Is statistics rpc enabled property type. + */ + @Deprecated + IS_STATISTICS_RPC_ENABLED, + /** + * Use single layer serialization property type. + */ + USE_SINGLE_LAYER_SERIALIZATION, + /** + * Rpc requests quota property type. + */ + RPC_REQUESTS_QUOTA, + /** + * Global notification quota property type. + */ + GLOBAL_NOTIFICATION_QUOTA, + /** + * Thread pool min threads property type. + */ + THREAD_POOL_MIN_THREADS, + /** + * Thread pool max threads property type. + */ + THREAD_POOL_MAX_THREADS, + /** + * Thread pool timeout property type. + */ + THREAD_POOL_TIMEOUT; + + private static final Map KEY_VALUE_MAP; + + /** + * Get property type from property key + * + * @param key the property key + * @return the property type + */ + public static ConfigurationProperty forValue(final String key) { + return KEY_VALUE_MAP.get(key); + } + + static { + final ConfigurationProperty[] values = values(); + final ImmutableMap.Builder builder = ImmutableMap.builder(); + + for (final ConfigurationProperty value : values) { + builder.put(value.toString(), value); + } + + KEY_VALUE_MAP = builder.build(); + } + + /** + * Converts enum name to property key + * + * @return the property key + */ + @Override + public String toString() { + return this.name().toLowerCase().replace('_', '-'); + } +} diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationService.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationService.java new file mode 100644 index 0000000000..7b61dcb576 --- /dev/null +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationService.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.configuration; + +import java.util.Map; +import java.util.function.Function; +import javax.annotation.Nonnull; + +/** + * Manages OpenFlowPlugin configuration + */ +public interface ConfigurationService extends AutoCloseable { + + /** + * Update map of properties. + * + * @param properties properties + */ + void update(@Nonnull Map properties); + + /** + * Register listener for configuration changes. + * + * @param listener the listener + * @return the auto closeable listener registration + */ + @Nonnull + AutoCloseable registerListener(@Nonnull ConfigurationListener listener); + + /** + * Get single property from configuration service. + * + * @param property type + * @param key property key + * @param transformer property type transformer + * @return property property + */ + @Nonnull + T getProperty(@Nonnull String key, @Nonnull Function transformer); + +} diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationServiceFactory.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationServiceFactory.java new file mode 100644 index 0000000000..2a60b12d40 --- /dev/null +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/configuration/ConfigurationServiceFactory.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.configuration; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig; +import org.osgi.framework.BundleContext; + +/** + * Factory for creating ConfigurationService instances. + */ +public interface ConfigurationServiceFactory { + ConfigurationService newInstance(OpenflowProviderConfig providerConfig, + BundleContext bundleContext); +} \ No newline at end of file diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionManager.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionManager.java index f2f4467ab9..9ba367d0d6 100644 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionManager.java +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionManager.java @@ -32,9 +32,4 @@ public interface ConnectionManager extends SwitchConnectionHandler { */ void setDeviceDisconnectedHandler(DeviceDisconnectedHandler deviceDisconnectedHandler); - /** - * Setter for echo reply timeout. - * @param echoReplyTimeout {@link Long} timeout - */ - void setEchoReplyTimeout(long echoReplyTimeout); } diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java index e0c936a440..87e25b08b5 100644 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java @@ -9,7 +9,6 @@ package org.opendaylight.openflowplugin.api.openflow.device; import com.google.common.util.concurrent.ListenableFuture; -import io.netty.util.Timeout; import java.util.List; import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService; @@ -66,17 +65,6 @@ public interface DeviceContext extends */ TranslatorLibrary oook(); - /** - * store cancellable timeout handler of currently running barrier task. - */ - void setCurrentBarrierTimeout(Timeout timeout); - - /** - * Getter. - * @return cancellable timeout handle of currently running barrier task - */ - Timeout getBarrierTaskTimeout(); - void setNotificationPublishService(NotificationPublishService notificationPublishService); MessageSpy getMessageSpy(); @@ -100,8 +88,6 @@ public interface DeviceContext extends */ ItemLifeCycleRegistry getItemLifeCycleSourceRegistry(); - void setSwitchFeaturesMandatory(boolean switchFeaturesMandatory); - /** * Setter for sal role service. * @param salRoleService Role Service diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceManager.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceManager.java index 9341567559..223cb4c14f 100644 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceManager.java +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceManager.java @@ -32,20 +32,6 @@ public interface DeviceManager extends */ void initialize(); - void setFlowRemovedNotificationOn(boolean value); - - boolean isFlowRemovedNotificationOn(); - - void setGlobalNotificationQuota(long globalNotificationQuota); - - void setSwitchFeaturesMandatory(boolean switchFeaturesMandatory); - - void setSkipTableFeatures(boolean skipTableFeatures); - - void setBarrierCountLimit(int barrierCountLimit); - - void setBarrierInterval(long barrierTimeoutLimit); - CheckedFuture removeDeviceFromOperationalDS( @Nonnull KeyedInstanceIdentifier ii); diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChainHolder.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChainHolder.java index 9b1f96d361..e814fec2c1 100644 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChainHolder.java +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChainHolder.java @@ -7,10 +7,7 @@ */ package org.opendaylight.openflowplugin.api.openflow.lifecycle; -import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener; -import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService; -import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.openflowplugin.api.openflow.OFPManager; import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext; import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo; @@ -53,18 +50,6 @@ public interface ContextChainHolder extends */ void destroyContextChain(DeviceInfo deviceInfo); - /** - * Provider is needed to register cluster singleton service. - * @param singletonServicesProvider provider - */ - void addSingletonServicesProvider(ClusterSingletonServiceProvider singletonServicesProvider); - - /** - * Register EOS listener. - * @param entityOwnershipService EOS services - */ - void changeEntityOwnershipService(@Nonnull EntityOwnershipService entityOwnershipService); - @Override void close() throws Exception; diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/rpc/RpcManager.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/rpc/RpcManager.java index 42e7440cef..987fe92020 100644 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/rpc/RpcManager.java +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/rpc/RpcManager.java @@ -18,10 +18,6 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo; */ public interface RpcManager extends OFPManager { - void setStatisticsRpcEnabled(boolean statisticsRpcEnabled); - - void setRpcRequestQuota(int rpcRequestQuota); - RpcContext createContext(@Nonnull DeviceInfo deviceInfo, @Nonnull DeviceContext deviceContext); } diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/statistics/StatisticsManager.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/statistics/StatisticsManager.java index faa66f9f51..5bf156a236 100644 --- a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/statistics/StatisticsManager.java +++ b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/statistics/StatisticsManager.java @@ -33,12 +33,6 @@ public interface StatisticsManager extends OFPManager { @Override void close(); - void setIsStatisticsPollingOn(boolean isStatisticsPollingOn); - - void setBasicTimerDelay(long basicTimerDelay); - - void setMaximumTimerDelay(long maximumTimerDelay); - StatisticsContext createContext(@Nonnull DeviceContext deviceContext); } diff --git a/openflowplugin-blueprint-config/src/main/resources/initial/openflowplugin.cfg b/openflowplugin-blueprint-config/src/main/resources/initial/openflowplugin.cfg index a3759234c5..417c34bf68 100644 --- a/openflowplugin-blueprint-config/src/main/resources/initial/openflowplugin.cfg +++ b/openflowplugin-blueprint-config/src/main/resources/initial/openflowplugin.cfg @@ -104,17 +104,23 @@ # # ############################################################################# +# # Disable the default switch reconciliation mechanism +# # disable-reconciliation=false +# # Enable stale marking for switch reconciliation. Once user enable this feature # forwarding rule manager will keep track of any change to the config data store # while the switch is disconnected from controller. Once switch reconnect to the # controller it will apply those changes to the switch and do the reconciliation # of other configuration as well. # NOTE: This option will be effective only if disable_reconciliation=false. +# # stale-marking-enabled=false +# # Number of time forwarding rules manager should retry to reconcile any specific # configuration. +# # reconciliation-retry-count=5 diff --git a/openflowplugin-blueprint-config/src/main/resources/org/opendaylight/blueprint/openflowplugin.xml b/openflowplugin-blueprint-config/src/main/resources/org/opendaylight/blueprint/openflowplugin.xml index 088c8cbb53..0a493f336c 100644 --- a/openflowplugin-blueprint-config/src/main/resources/org/opendaylight/blueprint/openflowplugin.xml +++ b/openflowplugin-blueprint-config/src/main/resources/org/opendaylight/blueprint/openflowplugin.xml @@ -16,14 +16,33 @@ + + + + - + + + + + + + - - + + @@ -35,10 +54,6 @@ - - diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderFactoryImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderFactoryImpl.java index 6044298c19..d28e40edba 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderFactoryImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderFactoryImpl.java @@ -7,26 +7,16 @@ */ package org.opendaylight.openflowplugin.impl; -import java.io.IOException; -import java.util.Enumeration; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Optional; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService; import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider; -import org.opendaylight.openflowplugin.api.OFConstants; -import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginConfigurationService.PropertyType; import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider; import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProviderFactory; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig; -import org.osgi.framework.BundleContext; -import org.osgi.service.cm.Configuration; -import org.osgi.service.cm.ConfigurationAdmin; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,18 +29,16 @@ public class OpenFlowPluginProviderFactoryImpl implements OpenFlowPluginProvider private static final Logger LOG = LoggerFactory.getLogger(OpenFlowPluginProviderFactoryImpl.class); @Override - public OpenFlowPluginProvider newInstance(final OpenflowProviderConfig providerConfig, + public OpenFlowPluginProvider newInstance(final ConfigurationService configurationService, final DataBroker dataBroker, final RpcProviderRegistry rpcRegistry, final NotificationPublishService notificationPublishService, final EntityOwnershipService entityOwnershipService, final List switchConnectionProviders, - final ClusterSingletonServiceProvider singletonServiceProvider, - final BundleContext bundleContext) { - + final ClusterSingletonServiceProvider singletonServiceProvider) { LOG.info("Initializing new OFP southbound."); - - final OpenFlowPluginProviderImpl openflowPluginProvider = new OpenFlowPluginProviderImpl( + final OpenFlowPluginProvider openflowPluginProvider = new OpenFlowPluginProviderImpl( + configurationService, switchConnectionProviders, dataBroker, rpcRegistry, @@ -58,48 +46,6 @@ public class OpenFlowPluginProviderFactoryImpl implements OpenFlowPluginProvider singletonServiceProvider, entityOwnershipService); - LOG.info("Loading configuration from YANG file"); - openflowPluginProvider.updateProperty(PropertyType.RPC_REQUESTS_QUOTA, providerConfig.getRpcRequestsQuota().getValue()); - openflowPluginProvider.updateProperty(PropertyType.GLOBAL_NOTIFICATION_QUOTA, providerConfig.getGlobalNotificationQuota()); - openflowPluginProvider.updateProperty(PropertyType.SWITCH_FEATURES_MANDATORY, providerConfig.isSwitchFeaturesMandatory()); - openflowPluginProvider.updateProperty(PropertyType.ENABLE_FLOW_REMOVED_NOTIFICATION, providerConfig.isEnableFlowRemovedNotification()); - openflowPluginProvider.updateProperty(PropertyType.IS_STATISTICS_RPC_ENABLED, providerConfig.isIsStatisticsRpcEnabled()); - openflowPluginProvider.updateProperty(PropertyType.BARRIER_COUNT_LIMIT, providerConfig.getBarrierCountLimit().getValue()); - openflowPluginProvider.updateProperty(PropertyType.BARRIER_INTERVAL_TIMEOUT_LIMIT, providerConfig.getBarrierIntervalTimeoutLimit().getValue()); - openflowPluginProvider.updateProperty(PropertyType.ECHO_REPLY_TIMEOUT, providerConfig.getEchoReplyTimeout().getValue()); - openflowPluginProvider.updateProperty(PropertyType.IS_STATISTICS_POLLING_ON, providerConfig.isIsStatisticsPollingOn()); - openflowPluginProvider.updateProperty(PropertyType.SKIP_TABLE_FEATURES, providerConfig.isSkipTableFeatures()); - openflowPluginProvider.updateProperty(PropertyType.BASIC_TIMER_DELAY, providerConfig.getBasicTimerDelay().getValue()); - openflowPluginProvider.updateProperty(PropertyType.MAXIMUM_TIMER_DELAY, providerConfig.getMaximumTimerDelay().getValue()); - openflowPluginProvider.updateProperty(PropertyType.USE_SINGLE_LAYER_SERIALIZATION, providerConfig.isUseSingleLayerSerialization()); - openflowPluginProvider.updateProperty(PropertyType.THREAD_POOL_MIN_THREADS, providerConfig.getThreadPoolMinThreads()); - openflowPluginProvider.updateProperty(PropertyType.THREAD_POOL_MAX_THREADS, providerConfig.getThreadPoolMaxThreads().getValue()); - openflowPluginProvider.updateProperty(PropertyType.THREAD_POOL_TIMEOUT, providerConfig.getThreadPoolTimeout()); - - LOG.info("Loading configuration from properties file"); - Optional.ofNullable(bundleContext.getServiceReference(ConfigurationAdmin.class.getName())).ifPresent(serviceReference -> { - final ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) bundleContext.getService(serviceReference); - - try { - final Configuration configuration = configurationAdmin.getConfiguration(OFConstants.CONFIG_FILE_ID); - - Optional.ofNullable(configuration.getProperties()).ifPresent(properties -> { - final Enumeration keys = properties.keys(); - final Map mapProperties = new HashMap<>(properties.size()); - - while (keys.hasMoreElements()) { - final String key = keys.nextElement(); - final Object value = properties.get(key); - mapProperties.put(key, value); - } - - openflowPluginProvider.update(mapProperties); - }); - } catch (IOException e) { - LOG.debug("Failed to load " + OFConstants.CONFIG_FILE_ID + " configuration file", e); - } - }); - openflowPluginProvider.initialize(); return openflowPluginProvider; } diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java index 421c60ae8c..3b244fd339 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java @@ -8,7 +8,6 @@ package org.opendaylight.openflowplugin.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; @@ -17,14 +16,12 @@ import io.netty.util.Timer; import java.lang.management.ManagementFactory; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.function.Consumer; import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.management.InstanceAlreadyExistsException; @@ -40,11 +37,10 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider; -import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginConfigurationService; import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService; import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionManager; import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager; -import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainHolder; 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; @@ -52,6 +48,7 @@ import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderK import org.opendaylight.openflowplugin.extension.api.ExtensionConverterRegistrator; import org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegistratorProvider; import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterManager; +import org.opendaylight.openflowplugin.impl.configuration.OpenFlowProviderConfigImpl; import org.opendaylight.openflowplugin.impl.connection.ConnectionManagerImpl; import org.opendaylight.openflowplugin.impl.device.DeviceManagerImpl; import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider; @@ -69,10 +66,11 @@ import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConve import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory; import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil; +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; -public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenFlowPluginConfigurationService, OpenFlowPluginExtensionRegistratorProvider { +public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenFlowPluginExtensionRegistratorProvider { private static final Logger LOG = LoggerFactory.getLogger(OpenFlowPluginProviderImpl.class); @@ -95,36 +93,21 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF private final ConvertorManager convertorManager; private final RpcProviderRegistry rpcProviderRegistry; private final ClusterSingletonServiceProvider singletonServicesProvider; + private final OpenflowProviderConfig config; private final EntityOwnershipService entityOwnershipService; - private ContextChainHolder contextChainHolder; - private int rpcRequestsQuota; - private long globalNotificationQuota; - private long barrierInterval; - private int barrierCountLimit; - private long echoReplyTimeout; private DeviceManager deviceManager; private RpcManager rpcManager; private StatisticsManager statisticsManager; private ConnectionManager connectionManager; - private boolean switchFeaturesMandatory; - private boolean isStatisticsPollingOn; - private boolean isStatisticsRpcEnabled; - private boolean isFlowRemovedNotificationOn; - private boolean skipTableFeatures; - private long basicTimerDelay; - private long maximumTimerDelay; - private boolean useSingleLayerSerialization; private ThreadPoolExecutor threadPool; - private int threadPoolMinThreads; - private int threadPoolMaxThreads; - private long threadPoolTimeout; - private boolean initialized = false; + private ContextChainHolderImpl contextChainHolder; public static MessageIntelligenceAgency getMessageIntelligenceAgency() { return MESSAGE_INTELLIGENCE_AGENCY; } - OpenFlowPluginProviderImpl(final List switchConnectionProviders, + OpenFlowPluginProviderImpl(final ConfigurationService configurationService, + final List switchConnectionProviders, final DataBroker dataBroker, final RpcProviderRegistry rpcProviderRegistry, final NotificationPublishService notificationPublishService, @@ -139,13 +122,14 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF convertorManager = ConvertorManagerFactory.createDefaultManager(); extensionConverterManager = new ExtensionConverterManagerImpl(); deviceInitializerProvider = DeviceInitializerProviderFactory.createDefaultProvider(); + config = new OpenFlowProviderConfigImpl(configurationService); } private void startSwitchConnections() { Futures.addCallback(Futures.allAsList(switchConnectionProviders.stream().map(switchConnectionProvider -> { // Inject OpenFlowPlugin custom serializers and deserializers into OpenFlowJava - if (useSingleLayerSerialization) { + if (config.isUseSingleLayerSerialization()) { SerializerInjector.injectSerializers(switchConnectionProvider); DeserializerInjector.injectDeserializers(switchConnectionProvider); } else { @@ -171,7 +155,7 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF private ListenableFuture> shutdownSwitchConnections() { final ListenableFuture> listListenableFuture = Futures.allAsList(switchConnectionProviders.stream().map(switchConnectionProvider -> { // Revert deserializers to their original state - if (useSingleLayerSerialization) { + if (config.isUseSingleLayerSerialization()) { DeserializerInjector.revertDeserializers(switchConnectionProvider); } @@ -196,6 +180,8 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF @Override public void initialize() { + registerMXBean(MESSAGE_INTELLIGENCE_AGENCY, MESSAGE_INTELLIGENCE_AGENCY_MX_BEAN_NAME); + // TODO: copied from OpenFlowPluginProvider (Helium) misusesing the old way of distributing extension converters // TODO: rewrite later! OFSessionUtil.getSessionManager().setExtensionConverterProvider(extensionConverterManager); @@ -204,296 +190,52 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF // 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), + config.getThreadPoolMinThreads(), + config.getThreadPoolMaxThreads().getValue(), + config.getThreadPoolTimeout(), TimeUnit.SECONDS, new SynchronousQueue<>(), POOL_NAME); - - contextChainHolder = new ContextChainHolderImpl(hashedWheelTimer, threadPool); - contextChainHolder.changeEntityOwnershipService(entityOwnershipService); - - connectionManager = new ConnectionManagerImpl(threadPool); - connectionManager.setEchoReplyTimeout(echoReplyTimeout); - - registerMXBean(MESSAGE_INTELLIGENCE_AGENCY, MESSAGE_INTELLIGENCE_AGENCY_MX_BEAN_NAME); - - contextChainHolder.addSingletonServicesProvider(singletonServicesProvider); - deviceManager = new DeviceManagerImpl( + config, dataBroker, getMessageIntelligenceAgency(), notificationPublishService, hashedWheelTimer, convertorManager, - deviceInitializerProvider, - useSingleLayerSerialization); - - deviceManager.setGlobalNotificationQuota(globalNotificationQuota); - deviceManager.setSwitchFeaturesMandatory(switchFeaturesMandatory); - deviceManager.setBarrierInterval(barrierInterval); - deviceManager.setBarrierCountLimit(barrierCountLimit); - deviceManager.setFlowRemovedNotificationOn(isFlowRemovedNotificationOn); - deviceManager.setSkipTableFeatures(skipTableFeatures); + deviceInitializerProvider); + TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager); ((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager); - rpcManager = new RpcManagerImpl(rpcProviderRegistry, extensionConverterManager, convertorManager, notificationPublishService); - rpcManager.setRpcRequestQuota(rpcRequestsQuota); - - statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, hashedWheelTimer, convertorManager); - statisticsManager.setBasicTimerDelay(basicTimerDelay); - statisticsManager.setMaximumTimerDelay(maximumTimerDelay); - statisticsManager.setIsStatisticsPollingOn(isStatisticsPollingOn); - - // Device connection handler moved from device manager to context holder - connectionManager.setDeviceConnectedHandler(contextChainHolder); - - /* Termination Phase ordering - OFP Device Context suite */ - connectionManager.setDeviceDisconnectedHandler(contextChainHolder); + rpcManager = new RpcManagerImpl( + config, + rpcProviderRegistry, + extensionConverterManager, + convertorManager, + notificationPublishService); - rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled); + statisticsManager = new StatisticsManagerImpl( + config, + rpcProviderRegistry, + hashedWheelTimer, + convertorManager); - TranslatorLibraryUtil.injectBasicTranslatorLibrary(deviceManager, convertorManager); - deviceManager.initialize(); + contextChainHolder = new ContextChainHolderImpl( + hashedWheelTimer, + threadPool, + singletonServicesProvider, + entityOwnershipService); contextChainHolder.addManager(deviceManager); contextChainHolder.addManager(statisticsManager); contextChainHolder.addManager(rpcManager); - startSwitchConnections(); - initialized = true; - } - - - @Override - public void update(@Nonnull final Map properties) { - properties.forEach((key, value) -> { - final PropertyType propertyType = PropertyType.forValue(key); - - if (Objects.nonNull(propertyType)) { - updateProperty(propertyType, value); - } - }); - } - - private void doPropertyUpdate(final PropertyType propertyType, - final boolean modifiable, - final Object origValue, - final Object newValue, - final Consumer successCallback) { - if (initialized) { - if (Objects.equals(origValue, newValue)) { - LOG.debug("{} config parameter is already set to {})", propertyType, origValue); - return; - } else if (!modifiable) { - LOG.warn("{} update ({} -> {}) is not allowed after controller start", propertyType, origValue, newValue); - return; - } - } - - successCallback.accept(newValue); - LOG.info("{} config parameter is updated ({} -> {})", propertyType, origValue, newValue); - } - - @Override - public void updateProperty(@Nonnull final PropertyType key, @Nonnull final Object value) { - try { - final String sValue = value.toString(); - final Consumer successCallback; - final boolean modifiable; - final Object oldValue; - final Object newValue; - - switch (key) { - case RPC_REQUESTS_QUOTA: - successCallback = (result) -> { - rpcRequestsQuota = (int) result; - - if (initialized) { - rpcManager.setRpcRequestQuota(rpcRequestsQuota); - } - }; - - oldValue = rpcRequestsQuota; - newValue = Integer.valueOf(sValue); - modifiable = true; - break; - case SWITCH_FEATURES_MANDATORY: - successCallback = (result) -> { - switchFeaturesMandatory = (boolean) result; - - if (initialized) { - deviceManager.setSwitchFeaturesMandatory(switchFeaturesMandatory); - } - }; - - oldValue = switchFeaturesMandatory; - newValue = Boolean.valueOf(sValue); - modifiable = true; - break; - case GLOBAL_NOTIFICATION_QUOTA: - successCallback = (result) -> { - globalNotificationQuota = (long) result; - - if (initialized) { - deviceManager.setGlobalNotificationQuota(globalNotificationQuota); - } - }; - - oldValue = globalNotificationQuota; - newValue = Long.valueOf(sValue); - modifiable = true; - break; - case IS_STATISTICS_POLLING_ON: - successCallback = (result) -> { - isStatisticsPollingOn = (boolean) result; - - if (initialized) { - statisticsManager.setIsStatisticsPollingOn(isStatisticsPollingOn); - } - }; - - oldValue = isStatisticsPollingOn; - newValue = Boolean.valueOf(sValue); - modifiable = true; - break; - case IS_STATISTICS_RPC_ENABLED: - successCallback = (result) -> { - isStatisticsRpcEnabled = (boolean) result; - - if (initialized) { - rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled); - } - }; - - oldValue = isStatisticsRpcEnabled; - newValue = Boolean.valueOf(sValue); - modifiable = true; - break; - case BARRIER_INTERVAL_TIMEOUT_LIMIT: - successCallback = (result) -> { - barrierInterval = (long) result; - - if (initialized) { - deviceManager.setBarrierInterval(barrierInterval); - } - }; - - oldValue = barrierInterval; - newValue = Long.valueOf(sValue); - modifiable = true; - break; - case BARRIER_COUNT_LIMIT: - successCallback = (result) -> { - barrierCountLimit = (int) result; - - if (initialized) { - deviceManager.setBarrierCountLimit(barrierCountLimit); - } - }; - - oldValue = barrierCountLimit; - newValue = Integer.valueOf(sValue); - modifiable = true; - break; - case ECHO_REPLY_TIMEOUT: - successCallback = (result) -> { - echoReplyTimeout = (long) result; - - if (initialized) { - connectionManager.setEchoReplyTimeout(echoReplyTimeout); - } - }; - - oldValue = echoReplyTimeout; - newValue = Long.valueOf(sValue); - modifiable = true; - break; - case THREAD_POOL_MIN_THREADS: - successCallback = (result) -> threadPoolMinThreads = (int) result; - oldValue = threadPoolMinThreads; - newValue = Integer.valueOf(sValue); - modifiable = false; - break; - case THREAD_POOL_MAX_THREADS: - successCallback = (result) -> threadPoolMaxThreads = (int) result; - oldValue = threadPoolMaxThreads; - newValue = Integer.valueOf(sValue); - modifiable = false; - break; - case THREAD_POOL_TIMEOUT: - successCallback = (result) -> threadPoolTimeout = (long) result; - oldValue = threadPoolTimeout; - newValue = Long.valueOf(sValue); - modifiable = false; - break; - case ENABLE_FLOW_REMOVED_NOTIFICATION: - successCallback = (result) -> { - isFlowRemovedNotificationOn = (boolean) result; - - if (initialized) { - deviceManager.setFlowRemovedNotificationOn(isFlowRemovedNotificationOn); - } - }; - - oldValue = isFlowRemovedNotificationOn; - newValue = Boolean.valueOf(sValue); - modifiable = true; - break; - case SKIP_TABLE_FEATURES: - successCallback = (result) -> { - skipTableFeatures = (boolean) result; - - if (initialized) { - deviceManager.setSkipTableFeatures(skipTableFeatures); - } - }; - - oldValue = skipTableFeatures; - newValue = Boolean.valueOf(sValue); - modifiable = true; - break; - case BASIC_TIMER_DELAY: - successCallback = (result) -> { - basicTimerDelay = (long) result; - - if (initialized) { - statisticsManager.setBasicTimerDelay(basicTimerDelay); - } - }; - - oldValue = basicTimerDelay; - newValue = Long.valueOf(sValue); - modifiable = true; - break; - case MAXIMUM_TIMER_DELAY: - successCallback = (result) -> { - maximumTimerDelay = (long) result; - - if (initialized) { - statisticsManager.setMaximumTimerDelay(maximumTimerDelay); - } - }; - - oldValue = maximumTimerDelay; - newValue = Long.valueOf(sValue); - modifiable = true; - break; - case USE_SINGLE_LAYER_SERIALIZATION: - successCallback = (result) -> useSingleLayerSerialization = (boolean) result; - oldValue = useSingleLayerSerialization; - newValue = Boolean.valueOf(sValue); - modifiable = false; - break; - default: - return; - } + connectionManager = new ConnectionManagerImpl(config, threadPool); + connectionManager.setDeviceConnectedHandler(contextChainHolder); + connectionManager.setDeviceDisconnectedHandler(contextChainHolder); - doPropertyUpdate(key, modifiable, oldValue, newValue, successCallback); - } catch (final Exception ex) { - LOG.warn("Failed to read configuration property '{}={}', error: {}", key, value, ex); - } + deviceManager.initialize(); + startSwitchConnections(); } @Override @@ -503,8 +245,6 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF @Override public void close() { - initialized = false; - try { shutdownSwitchConnections().get(10, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/configuration/ConfigurationServiceFactoryImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/configuration/ConfigurationServiceFactoryImpl.java new file mode 100644 index 0000000000..834b595fdc --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/configuration/ConfigurationServiceFactoryImpl.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.configuration; + +import com.google.common.base.Verify; +import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import javax.annotation.Nonnull; +import org.opendaylight.openflowplugin.api.OFConstants; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationListener; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationProperty; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationServiceFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig; +import org.osgi.framework.BundleContext; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConfigurationServiceFactoryImpl implements ConfigurationServiceFactory { + private static final Logger LOG = LoggerFactory.getLogger(ConfigurationServiceFactory.class); + + @Override + public ConfigurationService newInstance(final OpenflowProviderConfig providerConfig, final BundleContext bundleContext) { + return new ConfigurationServiceImpl(providerConfig, bundleContext); + } + + private static final class ConfigurationServiceImpl implements ConfigurationService { + private final Map propertyMap = new HashMap<>(); + private final List listeners = new ArrayList<>(); + + ConfigurationServiceImpl(final OpenflowProviderConfig providerConfig, final BundleContext bundleContext) { + LOG.info("Loading properties from '{}' YANG file", OpenflowProviderConfig.QNAME); + update(ImmutableMap + .builder() + .put(ConfigurationProperty.RPC_REQUESTS_QUOTA.toString(), + providerConfig.getRpcRequestsQuota().getValue().toString()) + .put(ConfigurationProperty.GLOBAL_NOTIFICATION_QUOTA.toString(), + providerConfig.getGlobalNotificationQuota().toString()) + .put(ConfigurationProperty.SWITCH_FEATURES_MANDATORY.toString(), + providerConfig.isSwitchFeaturesMandatory().toString()) + .put(ConfigurationProperty.ENABLE_FLOW_REMOVED_NOTIFICATION.toString(), + providerConfig.isEnableFlowRemovedNotification().toString()) + .put(ConfigurationProperty.IS_STATISTICS_RPC_ENABLED.toString(), + providerConfig.isIsStatisticsRpcEnabled().toString()) + .put(ConfigurationProperty.BARRIER_COUNT_LIMIT.toString(), + providerConfig.getBarrierCountLimit().getValue().toString()) + .put(ConfigurationProperty.BARRIER_INTERVAL_TIMEOUT_LIMIT.toString(), + providerConfig.getBarrierIntervalTimeoutLimit().getValue().toString()) + .put(ConfigurationProperty.ECHO_REPLY_TIMEOUT.toString(), + providerConfig.getEchoReplyTimeout().getValue().toString()) + .put(ConfigurationProperty.IS_STATISTICS_POLLING_ON.toString(), + providerConfig.isIsStatisticsPollingOn().toString()) + .put(ConfigurationProperty.SKIP_TABLE_FEATURES.toString(), + providerConfig.isSkipTableFeatures().toString()) + .put(ConfigurationProperty.BASIC_TIMER_DELAY.toString(), + providerConfig.getBasicTimerDelay().getValue().toString()) + .put(ConfigurationProperty.MAXIMUM_TIMER_DELAY.toString(), + providerConfig.getMaximumTimerDelay().getValue().toString()) + .put(ConfigurationProperty.USE_SINGLE_LAYER_SERIALIZATION.toString(), + providerConfig.isUseSingleLayerSerialization().toString()) + .put(ConfigurationProperty.THREAD_POOL_MIN_THREADS.toString(), + providerConfig.getThreadPoolMinThreads().toString()) + .put(ConfigurationProperty.THREAD_POOL_MAX_THREADS.toString(), + providerConfig.getThreadPoolMaxThreads().getValue().toString()) + .put(ConfigurationProperty.THREAD_POOL_TIMEOUT.toString(), + providerConfig.getThreadPoolTimeout().toString()) + .build()); + + LOG.info("Loading configuration from '{}' configuration file", OFConstants.CONFIG_FILE_ID); + Optional.ofNullable(bundleContext.getServiceReference(ConfigurationAdmin.class.getName())).ifPresent(serviceReference -> { + final ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) bundleContext.getService(serviceReference); + + try { + final Configuration configuration = configurationAdmin.getConfiguration(OFConstants.CONFIG_FILE_ID); + + Optional.ofNullable(configuration.getProperties()).ifPresent(properties -> { + final Enumeration keys = properties.keys(); + final Map mapProperties = new HashMap<>(properties.size()); + + while (keys.hasMoreElements()) { + final String key = keys.nextElement(); + final String value = properties.get(key).toString(); + mapProperties.put(key, value); + } + + update(mapProperties); + }); + } catch (IOException e) { + LOG.debug("Failed to load {} configuration file. Error {}", OFConstants.CONFIG_FILE_ID, e); + } + }); + } + + @Override + public void update(@Nonnull final Map properties) { + properties.forEach((propertyName, newValue) -> { + final String originalValue = propertyMap.get(propertyName); + + if (Objects.nonNull(originalValue)) { + if (originalValue.equals(newValue)) { + return; + } + + LOG.info("{} configuration property was changed from '{}' to '{}'", propertyName, originalValue, newValue); + } else { + if (Objects.isNull(newValue)) { + return; + } + + LOG.info("{} configuration property was changed to '{}'", propertyName, newValue); + } + + propertyMap.put(propertyName, newValue); + listeners.forEach(listener -> listener.onPropertyChanged(propertyName, newValue)); + }); + } + + @Nonnull + @Override + public T getProperty(@Nonnull final String key, @Nonnull final Function transformer) { + return transformer.apply(propertyMap.get(key)); + } + + @Nonnull + @Override + public AutoCloseable registerListener(@Nonnull final ConfigurationListener listener) { + Verify.verify(!listeners.contains(listener)); + LOG.info("{} was registered as configuration listener to OpenFlowPlugin configuration service", listener); + listeners.add(listener); + propertyMap.forEach(listener::onPropertyChanged); + return () -> listeners.remove(listener); + } + + @Override + public void close() throws Exception { + propertyMap.clear(); + listeners.clear(); + } + } +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/configuration/OpenFlowProviderConfigImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/configuration/OpenFlowProviderConfigImpl.java new file mode 100644 index 0000000000..0fc9f1d13e --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/configuration/OpenFlowProviderConfigImpl.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.configuration; + +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationProperty; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint16Type; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint32Type; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig; +import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.binding.DataContainer; + +public class OpenFlowProviderConfigImpl implements OpenflowProviderConfig { + private final ConfigurationService service; + + public OpenFlowProviderConfigImpl(final ConfigurationService service) { + this.service = service; + } + + @Override + public NonZeroUint16Type getRpcRequestsQuota() { + final Integer property = service.getProperty( + ConfigurationProperty.RPC_REQUESTS_QUOTA.toString(), + Integer::valueOf); + + return new NonZeroUint16Type(property); + } + + @Override + public Boolean isSwitchFeaturesMandatory() { + return service.getProperty(ConfigurationProperty.SWITCH_FEATURES_MANDATORY.toString(), Boolean::valueOf); + } + + @Override + public Long getGlobalNotificationQuota() { + return service.getProperty(ConfigurationProperty.GLOBAL_NOTIFICATION_QUOTA.toString(), Long::valueOf); + } + + @Override + public Boolean isIsStatisticsPollingOn() { + return service.getProperty(ConfigurationProperty.IS_STATISTICS_POLLING_ON.toString(), Boolean::valueOf); + } + + @Override + public Boolean isIsStatisticsRpcEnabled() { + return service.getProperty(ConfigurationProperty.IS_STATISTICS_RPC_ENABLED.toString(), Boolean::valueOf); + } + + @Override + public NonZeroUint32Type getBarrierIntervalTimeoutLimit() { + final Long property = service.getProperty( + ConfigurationProperty.BARRIER_INTERVAL_TIMEOUT_LIMIT.toString(), + Long::valueOf); + + return new NonZeroUint32Type(property); + } + + @Override + public NonZeroUint16Type getBarrierCountLimit() { + final Integer property = service.getProperty( + ConfigurationProperty.BARRIER_COUNT_LIMIT.toString(), + Integer::valueOf); + + return new NonZeroUint16Type(property); + } + + @Override + public NonZeroUint32Type getEchoReplyTimeout() { + final Long property = service.getProperty( + ConfigurationProperty.ECHO_REPLY_TIMEOUT.toString(), + Long::valueOf); + + return new NonZeroUint32Type(property); + } + + @Override + public Integer getThreadPoolMinThreads() { + return service.getProperty(ConfigurationProperty.THREAD_POOL_MIN_THREADS.toString(), Integer::valueOf); + } + + @Override + public NonZeroUint16Type getThreadPoolMaxThreads() { + final Integer property = service.getProperty( + ConfigurationProperty.THREAD_POOL_MAX_THREADS.toString(), + Integer::valueOf); + + return new NonZeroUint16Type(property); + } + + @Override + public Long getThreadPoolTimeout() { + return service.getProperty(ConfigurationProperty.THREAD_POOL_TIMEOUT.toString(), Long::valueOf); + } + + @Override + public Boolean isEnableFlowRemovedNotification() { + return service.getProperty(ConfigurationProperty.ENABLE_FLOW_REMOVED_NOTIFICATION.toString(), Boolean::valueOf); + } + + @Override + public Boolean isSkipTableFeatures() { + return service.getProperty(ConfigurationProperty.SKIP_TABLE_FEATURES.toString(), Boolean::valueOf); + } + + @Override + public NonZeroUint32Type getBasicTimerDelay() { + final Long property = service.getProperty( + ConfigurationProperty.BASIC_TIMER_DELAY.toString(), + Long::valueOf); + + return new NonZeroUint32Type(property); + } + + @Override + public NonZeroUint32Type getMaximumTimerDelay() { + final Long property = service.getProperty( + ConfigurationProperty.MAXIMUM_TIMER_DELAY.toString(), + Long::valueOf); + + return new NonZeroUint32Type(property); + } + + @Override + public Boolean isUseSingleLayerSerialization() { + return service.getProperty(ConfigurationProperty.USE_SINGLE_LAYER_SERIALIZATION.toString(), Boolean::valueOf); + } + + @Override + public > E getAugmentation(java.lang.Class augmentationType) { + return null; + } + + @Override + public Class getImplementedInterface() { + return OpenflowProviderConfig.class; + } + +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImpl.java index 01877f5807..e1fb42fb76 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImpl.java @@ -28,6 +28,7 @@ import org.opendaylight.openflowplugin.openflow.md.core.ErrorHandlerSimpleImpl; import org.opendaylight.openflowplugin.openflow.md.core.HandshakeManagerImpl; 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.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,11 +40,12 @@ public class ConnectionManagerImpl implements ConnectionManager { private static final Logger LOG = LoggerFactory.getLogger(ConnectionManagerImpl.class); private static final boolean BITMAP_NEGOTIATION_ENABLED = true; private DeviceConnectedHandler deviceConnectedHandler; - private long echoReplyTimeout = 2000; + private final OpenflowProviderConfig config; private final ThreadPoolExecutor threadPool; private DeviceDisconnectedHandler deviceDisconnectedHandler; - public ConnectionManagerImpl(final ThreadPoolExecutor threadPool) { + public ConnectionManagerImpl(final OpenflowProviderConfig config, final ThreadPoolExecutor threadPool) { + this.config = config; this.threadPool = threadPool; } @@ -70,17 +72,13 @@ public class ConnectionManagerImpl implements ConnectionManager { new OpenflowProtocolListenerInitialImpl(connectionContext, handshakeContext); connectionAdapter.setMessageListener(ofMessageListener); - final SystemNotificationsListener systemListener = new SystemNotificationsListenerImpl(connectionContext, echoReplyTimeout, threadPool); + final SystemNotificationsListener systemListener = new SystemNotificationsListenerImpl( + connectionContext, config.getEchoReplyTimeout().getValue(), threadPool); connectionAdapter.setSystemListener(systemListener); LOG.trace("connection ballet finished"); } - /** - * @param connectionAdapter - * @param handshakeListener - * @return - */ private HandshakeManager createHandshakeManager(final ConnectionAdapter connectionAdapter, final HandshakeListener handshakeListener) { HandshakeManagerImpl handshakeManager = new HandshakeManagerImpl(connectionAdapter, @@ -108,9 +106,4 @@ public class ConnectionManagerImpl implements ConnectionManager { public void setDeviceDisconnectedHandler(final DeviceDisconnectedHandler deviceDisconnectedHandler) { this.deviceDisconnectedHandler = deviceDisconnectedHandler; } - - @Override - public void setEchoReplyTimeout(long echoReplyTimeout){ - this.echoReplyTimeout = echoReplyTimeout; - } } diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java index 92f28aa6af..71c0766f45 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java @@ -16,7 +16,6 @@ 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.HashedWheelTimer; -import io.netty.util.Timeout; import io.netty.util.TimerTask; import java.util.Collection; import java.util.HashSet; @@ -41,7 +40,6 @@ 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.MessageTranslator; import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; @@ -138,60 +136,60 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi private static final int LOW_WATERMARK = 1000; private static final int HIGH_WATERMARK = 2000; - private final MultipartWriterProvider writerProvider; - - private boolean initialized; - private SalRoleService salRoleService = null; + private final MultipartWriterProvider writerProvider; private final HashedWheelTimer hashedWheelTimer; - private volatile ConnectionContext primaryConnectionContext; private final DeviceState deviceState; private final DataBroker dataBroker; private final Collection> requestContexts = new HashSet<>(); - private TransactionChainManager transactionChainManager; - private DeviceFlowRegistry deviceFlowRegistry; - private DeviceGroupRegistry deviceGroupRegistry; - private DeviceMeterRegistry deviceMeterRegistry; - private PacketInRateLimiter packetInLimiter; private final MessageSpy messageSpy; private final ItemLifeCycleKeeper flowLifeCycleKeeper; - private NotificationPublishService notificationPublishService; - private Timeout barrierTaskTimeout; private final MessageTranslator portStatusTranslator; private final MessageTranslator packetInTranslator; private final MessageTranslator flowRemovedTranslator; private final TranslatorLibrary translatorLibrary; private final ItemLifeCycleRegistry itemLifeCycleSourceRegistry; - private ExtensionConverterProvider extensionConverterProvider; - private boolean skipTableFeatures; - private boolean switchFeaturesMandatory; - private DeviceInfo deviceInfo; private final ConvertorExecutor convertorExecutor; - private volatile ContextState state; - private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler; - private final DeviceManager myManager; private final DeviceInitializerProvider deviceInitializerProvider; + private final PacketInRateLimiter packetInLimiter; + private final DeviceInfo deviceInfo; + private final boolean skipTableFeatures; + private final boolean switchFeaturesMandatory; + private final boolean isFlowRemovedNotificationOn; private final boolean useSingleLayerSerialization; + private NotificationPublishService notificationPublishService; + private TransactionChainManager transactionChainManager; + private DeviceFlowRegistry deviceFlowRegistry; + private DeviceGroupRegistry deviceGroupRegistry; + private DeviceMeterRegistry deviceMeterRegistry; + private ExtensionConverterProvider extensionConverterProvider; + private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler; + private SalRoleService salRoleService; + private boolean initialized; private boolean hasState; private boolean isInitialTransactionSubmitted; + private volatile ConnectionContext primaryConnectionContext; + private volatile ContextState state; DeviceContextImpl( @Nonnull final ConnectionContext primaryConnectionContext, @Nonnull final DataBroker dataBroker, @Nonnull final MessageSpy messageSpy, @Nonnull final TranslatorLibrary translatorLibrary, - @Nonnull final DeviceManager contextManager, final ConvertorExecutor convertorExecutor, final boolean skipTableFeatures, final HashedWheelTimer hashedWheelTimer, final boolean useSingleLayerSerialization, - final DeviceInitializerProvider deviceInitializerProvider) { + final DeviceInitializerProvider deviceInitializerProvider, + final boolean isFlowRemovedNotificationOn, + final boolean switchFeaturesMandatory) { this.primaryConnectionContext = primaryConnectionContext; this.deviceInfo = primaryConnectionContext.getDeviceInfo(); this.hashedWheelTimer = hashedWheelTimer; this.deviceInitializerProvider = deviceInitializerProvider; - this.myManager = contextManager; + this.isFlowRemovedNotificationOn = isFlowRemovedNotificationOn; + this.switchFeaturesMandatory = switchFeaturesMandatory; this.deviceState = new DeviceStateImpl(); this.dataBroker = dataBroker; this.messageSpy = messageSpy; @@ -313,11 +311,9 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved flowRemovedNotification = flowRemovedTranslator.translate(flowRemoved, deviceInfo, null); - if(myManager.isFlowRemovedNotificationOn()) { + if (isFlowRemovedNotificationOn) { // Trigger off a notification notificationPublishService.offerNotification(flowRemovedNotification); - } else if(LOG.isDebugEnabled()) { - LOG.debug("For nodeId={} isNotificationFlowRemovedOn={}", getDeviceInfo().getLOGValue(), myManager.isFlowRemovedNotificationOn()); } final ItemLifecycleListener itemLifecycleListener = flowLifeCycleKeeper.getItemLifecycleListener(); @@ -463,16 +459,6 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi return translatorLibrary; } - @Override - public void setCurrentBarrierTimeout(final Timeout timeout) { - barrierTaskTimeout = timeout; - } - - @Override - public Timeout getBarrierTaskTimeout() { - return barrierTaskTimeout; - } - @Override public void setNotificationPublishService(final NotificationPublishService notificationPublishService) { this.notificationPublishService = notificationPublishService; @@ -520,11 +506,6 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi return this.transactionChainManager; } - @Override - public void setSwitchFeaturesMandatory(boolean switchFeaturesMandatory) { - this.switchFeaturesMandatory = switchFeaturesMandatory; - } - @Override public ListenableFuture stopClusterServices() { return initialized diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java index 407a5943d7..be466580ea 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java @@ -12,16 +12,13 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import io.netty.util.HashedWheelTimer; import io.netty.util.internal.ConcurrentSet; -import java.util.Collections; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; 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.NotificationPublishService; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; @@ -42,16 +39,15 @@ import org.opendaylight.openflowplugin.impl.connection.OutboundQueueProviderImpl import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProvider; import org.opendaylight.openflowplugin.impl.device.listener.OpenflowProtocolListenerFullImpl; import org.opendaylight.openflowplugin.impl.services.sal.SalRoleServiceImpl; +import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtil; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor; 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.NodeRemovedBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder; -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.NodeKey; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,60 +58,37 @@ import org.slf4j.LoggerFactory; public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProviderKeeper { private static final Logger LOG = LoggerFactory.getLogger(DeviceManagerImpl.class); - - private long globalNotificationQuota; - private boolean switchFeaturesMandatory; - private boolean isFlowRemovedNotificationOn; - private boolean skipTableFeatures; private static final int SPY_RATE = 10; + private final OpenflowProviderConfig config; private final DataBroker dataBroker; private final DeviceInitializerProvider deviceInitializerProvider; private final ConvertorExecutor convertorExecutor; - private TranslatorLibrary translatorLibrary; - private final ConcurrentMap deviceContexts = new ConcurrentHashMap<>(); private final Set> notificationCreateNodeSend = new ConcurrentSet<>(); - - private long barrierIntervalNanos; - private int barrierCountLimit; - - private ExtensionConverterProvider extensionConverterProvider; - private ScheduledThreadPoolExecutor spyPool; private final NotificationPublishService notificationPublishService; private final MessageSpy messageSpy; private final HashedWheelTimer hashedWheelTimer; - private final boolean useSingleLayerSerialization; + private TranslatorLibrary translatorLibrary; + private ExtensionConverterProvider extensionConverterProvider; + private ScheduledThreadPoolExecutor spyPool; - public DeviceManagerImpl(@Nonnull final DataBroker dataBroker, + public DeviceManagerImpl(@Nonnull final OpenflowProviderConfig config, + @Nonnull final DataBroker dataBroker, @Nonnull final MessageSpy messageSpy, - @Nullable final NotificationPublishService notificationPublishService, + @Nonnull final NotificationPublishService notificationPublishService, @Nonnull final HashedWheelTimer hashedWheelTimer, @Nonnull final ConvertorExecutor convertorExecutor, - @Nonnull final DeviceInitializerProvider deviceInitializerProvider, - final boolean useSingleLayerSerialization) { - + @Nonnull final DeviceInitializerProvider deviceInitializerProvider) { + this.config = config; this.dataBroker = dataBroker; this.deviceInitializerProvider = deviceInitializerProvider; - this.useSingleLayerSerialization = useSingleLayerSerialization; - - /* merge empty nodes to oper DS to predict any problems with missing parent for Node */ - final WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); - final NodesBuilder nodesBuilder = new NodesBuilder(); - nodesBuilder.setNode(Collections.emptyList()); - tx.merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), nodesBuilder.build()); - try { - tx.submit().get(); - } catch (ExecutionException | InterruptedException e) { - LOG.error("Creation of node failed.", e); - throw new IllegalStateException(e); - } - this.convertorExecutor = convertorExecutor; this.hashedWheelTimer = hashedWheelTimer; this.spyPool = new ScheduledThreadPoolExecutor(1); this.notificationPublishService = notificationPublishService; this.messageSpy = messageSpy; + DeviceInitializationUtil.makeEmptyNodes(dataBroker); } @Override @@ -153,42 +126,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi } @Override - public void setFlowRemovedNotificationOn(boolean isNotificationFlowRemovedOff) { - this.isFlowRemovedNotificationOn = isNotificationFlowRemovedOff; - } - - @Override - public boolean isFlowRemovedNotificationOn() { - return this.isFlowRemovedNotificationOn; - } - - @Override - public void setGlobalNotificationQuota(final long globalNotificationQuota) { - this.globalNotificationQuota = globalNotificationQuota; - } - - @Override - public void setSwitchFeaturesMandatory(final boolean switchFeaturesMandatory) { - this.switchFeaturesMandatory = switchFeaturesMandatory; - } - - @Override - public void setSkipTableFeatures(boolean skipTableFeaturesValue) { - skipTableFeatures = skipTableFeaturesValue; - } - - @Override - public void setBarrierCountLimit(final int barrierCountLimit) { - this.barrierCountLimit = barrierCountLimit; - } - - @Override - public void setBarrierInterval(final long barrierTimeoutLimit) { - this.barrierIntervalNanos = TimeUnit.MILLISECONDS.toNanos(barrierTimeoutLimit); - } - - @Override - public CheckedFuture removeDeviceFromOperationalDS(@Nonnull final KeyedInstanceIdentifier ii) { + public CheckedFuture removeDeviceFromOperationalDS(final KeyedInstanceIdentifier ii) { final WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction(); delWtx.delete(LogicalDatastoreType.OPERATIONAL, ii); final CheckedFuture delFuture = delWtx.submit(); @@ -225,8 +163,8 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi final OutboundQueueHandlerRegistration outboundQueueHandlerRegistration = connectionContext.getConnectionAdapter().registerOutboundQueueHandler( outboundQueueProvider, - barrierCountLimit, - barrierIntervalNanos); + config.getBarrierCountLimit().getValue(), + TimeUnit.MILLISECONDS.toNanos(config.getBarrierIntervalTimeoutLimit().getValue())); connectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration); @@ -235,15 +173,15 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi dataBroker, messageSpy, translatorLibrary, - this, convertorExecutor, - skipTableFeatures, + config.isSkipTableFeatures(), hashedWheelTimer, - useSingleLayerSerialization, - deviceInitializerProvider); + config.isUseSingleLayerSerialization(), + deviceInitializerProvider, + config.isEnableFlowRemovedNotification(), + config.isSwitchFeaturesMandatory()); deviceContext.setSalRoleService(new SalRoleServiceImpl(deviceContext, deviceContext)); - deviceContext.setSwitchFeaturesMandatory(switchFeaturesMandatory); ((ExtensionConverterProviderKeeper) deviceContext).setExtensionConverterProvider(extensionConverterProvider); deviceContext.setNotificationPublishService(notificationPublishService); @@ -262,7 +200,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi synchronized (deviceContexts) { final int deviceContextsSize = deviceContexts.size(); if (deviceContextsSize > 0) { - long freshNotificationLimit = globalNotificationQuota / deviceContextsSize; + long freshNotificationLimit = config.getGlobalNotificationQuota() / deviceContextsSize; if (freshNotificationLimit < 100) { freshNotificationLimit = 100; } diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF13DeviceInitializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF13DeviceInitializer.java index d119d8e18f..227d9c30c0 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF13DeviceInitializer.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/initialization/OF13DeviceInitializer.java @@ -61,7 +61,7 @@ public class OF13DeviceInitializer extends AbstractDeviceInitializer { DeviceStateUtil.setDeviceStateBasedOnV13Capabilities(deviceState, capabilities); // First process description reply, write data to DS and write consequent data if successful - return Futures.transformAsync( + return Futures.transformAsync( requestMultipart(MultipartType.OFPMPDESC, deviceContext), (AsyncFunction>, Void>) input -> { translateAndWriteResult( diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImpl.java index 6af910f106..0e7371067d 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImpl.java @@ -62,22 +62,28 @@ public class ContextChainHolderImpl implements ContextChainHolder { private static final String ASYNC_SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.AsyncServiceCloseEntityType"; private final Map contextChainMap = Collections.synchronizedMap(new HashMap<>()); + private final EntityOwnershipListenerRegistration eosListenerRegistration; + private final ClusterSingletonServiceProvider singletonServiceProvider; + private final ItemScheduler scheduler; + private final ExecutorService executorService; private DeviceManager deviceManager; private RpcManager rpcManager; private StatisticsManager statisticsManager; - private EntityOwnershipListenerRegistration eosListenerRegistration; - private ClusterSingletonServiceProvider singletonServicesProvider; - private final ItemScheduler scheduler; - private final ExecutorService executorService; - public ContextChainHolderImpl(final HashedWheelTimer timer, final ExecutorService executorService) { + public ContextChainHolderImpl(final HashedWheelTimer timer, + final ExecutorService executorService, + final ClusterSingletonServiceProvider singletonServiceProvider, + final EntityOwnershipService entityOwnershipService) { + this.singletonServiceProvider = singletonServiceProvider; + this.executorService = executorService; + this.eosListenerRegistration = Verify.verifyNotNull(entityOwnershipService.registerListener + (ASYNC_SERVICE_ENTITY_TYPE, this)); + this.scheduler = new ItemScheduler<>( timer, CHECK_ROLE_MASTER_TIMEOUT, CHECK_ROLE_MASTER_TOLERANCE, ContextChain::makeDeviceSlave); - - this.executorService = executorService; } @Override @@ -145,7 +151,7 @@ public class ContextChainHolderImpl implements ContextChainHolder { scheduler.add(deviceInfo, contextChain); scheduler.startIfNotRunning(); deviceContext.onPublished(); - contextChain.registerServices(this.singletonServicesProvider); + contextChain.registerServices(singletonServiceProvider); return contextChain; } @@ -182,11 +188,6 @@ public class ContextChainHolderImpl implements ContextChainHolder { return ConnectionStatus.MAY_CONTINUE; } - @Override - public void addSingletonServicesProvider(final ClusterSingletonServiceProvider singletonServicesProvider) { - this.singletonServicesProvider = singletonServicesProvider; - } - @Override public void onNotAbleToStartMastership(final DeviceInfo deviceInfo, @Nonnull final String reason, final boolean mandatory) { LOG.warn("Not able to set MASTER role on device {}, reason: {}", deviceInfo.getLOGValue(), reason); @@ -241,16 +242,6 @@ public class ContextChainHolderImpl implements ContextChainHolder { }); } - @Override - public void changeEntityOwnershipService(@Nonnull final EntityOwnershipService entityOwnershipService) { - if (Objects.nonNull(this.eosListenerRegistration)) { - LOG.warn("Entity ownership service listener is already registered."); - } else { - this.eosListenerRegistration = Verify.verifyNotNull(entityOwnershipService.registerListener - (ASYNC_SERVICE_ENTITY_TYPE, this)); - } - } - @VisibleForTesting boolean checkAllManagers() { return Objects.nonNull(deviceManager) && Objects.nonNull(rpcManager) && Objects.nonNull(statisticsManager); @@ -269,12 +260,7 @@ public class ContextChainHolderImpl implements ContextChainHolder { }); contextChainMap.clear(); - - - if (Objects.nonNull(eosListenerRegistration)) { - eosListenerRegistration.close(); - eosListenerRegistration = null; - } + eosListenerRegistration.close(); } @Override diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImpl.java index 917a5053f3..0ff516da0c 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImpl.java @@ -21,25 +21,27 @@ import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext; import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager; import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor; +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; public class RpcManagerImpl implements RpcManager { private static final Logger LOG = LoggerFactory.getLogger(RpcManagerImpl.class); + private final OpenflowProviderConfig config; private final RpcProviderRegistry rpcProviderRegistry; - private int rpcRequestQuota; private final ConcurrentMap contexts = new ConcurrentHashMap<>(); - private boolean isStatisticsRpcEnabled; private final ExtensionConverterProvider extensionConverterProvider; private final ConvertorExecutor convertorExecutor; private final NotificationPublishService notificationPublishService; - public RpcManagerImpl(final RpcProviderRegistry rpcProviderRegistry, + public RpcManagerImpl(final OpenflowProviderConfig config, + final RpcProviderRegistry rpcProviderRegistry, final ExtensionConverterProvider extensionConverterProvider, final ConvertorExecutor convertorExecutor, final NotificationPublishService notificationPublishService) { + this.config = config; this.rpcProviderRegistry = rpcProviderRegistry; this.extensionConverterProvider = extensionConverterProvider; this.convertorExecutor = convertorExecutor; @@ -64,26 +66,15 @@ public class RpcManagerImpl implements RpcManager { } } - - @Override - public void setStatisticsRpcEnabled(boolean statisticsRpcEnabled) { - isStatisticsRpcEnabled = statisticsRpcEnabled; - } - - @Override - public void setRpcRequestQuota(final int rpcRequestQuota) { - this.rpcRequestQuota = rpcRequestQuota; - } - public RpcContext createContext(final @Nonnull DeviceInfo deviceInfo, final @Nonnull DeviceContext deviceContext) { final RpcContextImpl rpcContext = new RpcContextImpl( rpcProviderRegistry, - rpcRequestQuota, + config.getRpcRequestsQuota().getValue(), deviceContext, extensionConverterProvider, convertorExecutor, notificationPublishService, - this.isStatisticsRpcEnabled); + config.isIsStatisticsRpcEnabled()); contexts.put(deviceInfo, rpcContext); return rpcContext; diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImpl.java index c943428cd8..b699f8b2f5 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImpl.java @@ -39,6 +39,7 @@ import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider; import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProviderFactory; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor; import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig; 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; @@ -55,14 +56,13 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag private static final Logger LOG = LoggerFactory.getLogger(StatisticsManagerImpl.class); private static final long DEFAULT_STATS_TIMEOUT_SEC = 50L; + @Nonnull + private final OpenflowProviderConfig config; private final ConvertorExecutor converterExecutor; private final ConcurrentMap contexts = new ConcurrentHashMap<>(); - private long basicTimerDelay; private long currentTimerDelay; - private long maximumTimerDelay; //wait time for next statistics - private StatisticsWorkMode workMode = StatisticsWorkMode.COLLECTALL; private final Semaphore workModeGuard = new Semaphore(1, true); private boolean isStatisticsPollingOn; @@ -70,9 +70,12 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag private final HashedWheelTimer hashedWheelTimer; - public StatisticsManagerImpl(@Nonnull final RpcProviderRegistry rpcProviderRegistry, + public StatisticsManagerImpl(@Nonnull final OpenflowProviderConfig config, + @Nonnull final RpcProviderRegistry rpcProviderRegistry, final HashedWheelTimer hashedWheelTimer, final ConvertorExecutor convertorExecutor) { + this.config = config; + currentTimerDelay = config.getBasicTimerDelay().getValue(); this.converterExecutor = convertorExecutor; this.controlServiceRegistration = Preconditions.checkNotNull(rpcProviderRegistry .addRpcImplementation(StatisticsManagerControlService.class, this)); @@ -170,14 +173,14 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag final long averageStatisticsGatheringTime = timeCounter.getAverageTimeBetweenMarks(); if (averageStatisticsGatheringTime > currentTimerDelay) { currentTimerDelay *= 2; - if (currentTimerDelay > maximumTimerDelay) { - currentTimerDelay = maximumTimerDelay; + if (currentTimerDelay > config.getMaximumTimerDelay().getValue()) { + currentTimerDelay = config.getMaximumTimerDelay().getValue(); } } else { - if (currentTimerDelay > basicTimerDelay) { + if (currentTimerDelay > config.getBasicTimerDelay().getValue()) { currentTimerDelay /= 2; } else { - currentTimerDelay = basicTimerDelay; + currentTimerDelay = config.getBasicTimerDelay().getValue(); } } } @@ -295,11 +298,6 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag } } - @Override - public void setIsStatisticsPollingOn(boolean isStatisticsPollingOn){ - this.isStatisticsPollingOn = isStatisticsPollingOn; - } - @Override public StatisticsContext createContext(@Nonnull final DeviceContext deviceContext) { @@ -333,15 +331,4 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag LOG.debug("Statistics context removed for node {}", deviceInfo.getLOGValue()); } } - - @Override - public void setBasicTimerDelay(final long basicTimerDelay) { - this.basicTimerDelay = basicTimerDelay; - this.currentTimerDelay = basicTimerDelay; - } - - @Override - public void setMaximumTimerDelay(final long maximumTimerDelay) { - this.maximumTimerDelay = maximumTimerDelay; - } } diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtil.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtil.java index f8248d3500..54f2d71318 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtil.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtil.java @@ -9,7 +9,11 @@ package org.opendaylight.openflowplugin.impl.util; import java.net.InetSocketAddress; +import java.util.Collections; import java.util.Optional; +import java.util.concurrent.ExecutionException; +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.openflowplugin.api.openflow.connection.ConnectionContext; import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo; @@ -25,6 +29,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta 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.FlowTableStatisticsDataBuilder; +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.openflow.protocol.rev130731.GetFeaturesOutputBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -40,9 +46,29 @@ public class DeviceInitializationUtil { } /** - * Create specified number of empty tables on device + * Merge empty nodes to operational DS to predict any problems with missing parent for node. + * + * @param dataBroker the data broker + */ + public static void makeEmptyNodes(final DataBroker dataBroker) { + final WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); + + try { + tx.merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), new NodesBuilder() + .setNode(Collections.emptyList()) + .build()); + tx.submit().get(); + } catch (ExecutionException | InterruptedException e) { + LOG.error("Creation of node failed.", e); + throw new IllegalStateException(e); + } + } + + /** + * Create specified number of empty tables on device. * FIXME: remove after ovs table features fix - * @param txFacade transaction facade + * + * @param txFacade transaction facade * @param deviceInfo device info * @param nrOfTables number of tables */ @@ -71,8 +97,9 @@ public class DeviceInitializationUtil { } /** - * Retrieve ip address from connection - * @param connectionContext connection context + * Retrieve ip address from connection. + * + * @param connectionContext connection context * @param instanceIdentifier instance identifier * @return ip address */ @@ -90,8 +117,9 @@ public class DeviceInitializationUtil { } /** - * Retrieve port number from connection - * @param connectionContext connection context + * Retrieve port number from connection. + * + * @param connectionContext connection context * @param instanceIdentifier instance identifier * @return port number */ @@ -110,7 +138,8 @@ public class DeviceInitializationUtil { } /** - * Retrieve switch features from connection + * Retrieve switch features from connection. + * * @param connectionContext connection context * @return switch features */ diff --git a/openflowplugin-impl/src/main/resources/org/opendaylight/blueprint/openflowplugin-impl.xml b/openflowplugin-impl/src/main/resources/org/opendaylight/blueprint/openflowplugin-impl.xml index 5b67ceaf70..f83753964c 100644 --- a/openflowplugin-impl/src/main/resources/org/opendaylight/blueprint/openflowplugin-impl.xml +++ b/openflowplugin-impl/src/main/resources/org/opendaylight/blueprint/openflowplugin-impl.xml @@ -1,10 +1,11 @@ + xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" + odl:use-default-for-reference-types="true"> + - - + + diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImplTest.java index 0162beb037..9f6abc99d7 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImplTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImplTest.java @@ -15,7 +15,6 @@ import static org.mockito.Mockito.when; import com.google.common.collect.Lists; import com.google.common.util.concurrent.Futures; -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,7 +29,8 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider; -import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginConfigurationService.PropertyType; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationProperty; +import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.StatisticsManagerControlService; @RunWith(MockitoJUnitRunner.class) @@ -63,11 +63,16 @@ public class OpenFlowPluginProviderImplTest { @Mock ClusterSingletonServiceProvider clusterSingletonServiceProvider; + @Mock + ConfigurationService configurationService; + private static final int 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 static final long BASIC_TIMER_DELAY = 1L; + private static final boolean USE_SINGLE_LAYER_SERIALIZATION = false; private OpenFlowPluginProviderImpl provider; @@ -78,25 +83,22 @@ public class OpenFlowPluginProviderImplTest { when(entityOwnershipService.registerListener(any(), any())).thenReturn(entityOwnershipListenerRegistration); when(rpcProviderRegistry.addRpcImplementation(eq(StatisticsManagerControlService.class), any())).thenReturn(controlServiceRegistration); when(switchConnectionProvider.startup()).thenReturn(Futures.immediateCheckedFuture(null)); + when(configurationService.getProperty(eq(ConfigurationProperty.USE_SINGLE_LAYER_SERIALIZATION.toString()), any())).thenReturn(USE_SINGLE_LAYER_SERIALIZATION); + when(configurationService.getProperty(eq(ConfigurationProperty.THREAD_POOL_MIN_THREADS.toString()), any())).thenReturn(THREAD_POOL_MIN_THREADS); + when(configurationService.getProperty(eq(ConfigurationProperty.THREAD_POOL_MAX_THREADS.toString()), any())).thenReturn(THREAD_POOL_MAX_THREADS); + when(configurationService.getProperty(eq(ConfigurationProperty.THREAD_POOL_TIMEOUT.toString()), any())).thenReturn(THREAD_POOL_TIMEOUT); + when(configurationService.getProperty(eq(ConfigurationProperty.RPC_REQUESTS_QUOTA.toString()), any())).thenReturn(RPC_REQUESTS_QUOTA); + when(configurationService.getProperty(eq(ConfigurationProperty.GLOBAL_NOTIFICATION_QUOTA.toString()), any())).thenReturn(GLOBAL_NOTIFICATION_QUOTA); + when(configurationService.getProperty(eq(ConfigurationProperty.BASIC_TIMER_DELAY.toString()), any())).thenReturn(BASIC_TIMER_DELAY); provider = new OpenFlowPluginProviderImpl( + configurationService, Lists.newArrayList(switchConnectionProvider), dataBroker, rpcProviderRegistry, notificationPublishService, clusterSingletonServiceProvider, entityOwnershipService); - - provider.updateProperty(PropertyType.THREAD_POOL_MIN_THREADS, THREAD_POOL_MIN_THREADS); - provider.updateProperty(PropertyType.THREAD_POOL_MAX_THREADS, THREAD_POOL_MAX_THREADS); - provider.updateProperty(PropertyType.THREAD_POOL_TIMEOUT, THREAD_POOL_TIMEOUT); - provider.updateProperty(PropertyType.RPC_REQUESTS_QUOTA, RPC_REQUESTS_QUOTA); - provider.updateProperty(PropertyType.GLOBAL_NOTIFICATION_QUOTA, GLOBAL_NOTIFICATION_QUOTA); - } - - @After - public void tearDown() throws Exception { - } @Test diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImplTest.java index 001df46d8d..d08bb28a1a 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImplTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImplTest.java @@ -37,6 +37,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint32Type; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; @@ -58,7 +60,7 @@ public class ConnectionManagerImplTest { @Captor private ArgumentCaptor ofpListenerAC; - private final static int ECHO_REPLY_TIMEOUT = 500; + private final static long ECHO_REPLY_TIMEOUT = 500; /** * before each test method @@ -69,8 +71,10 @@ public class ConnectionManagerImplTest { 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), "ofppool"); - connectionManagerImpl = new ConnectionManagerImpl(threadPool); - connectionManagerImpl.setEchoReplyTimeout(ECHO_REPLY_TIMEOUT); + connectionManagerImpl = new ConnectionManagerImpl(new OpenflowProviderConfigBuilder() + .setEchoReplyTimeout(new NonZeroUint32Type(ECHO_REPLY_TIMEOUT)) + .build(), threadPool); + connectionManagerImpl.setDeviceConnectedHandler(deviceConnectedHandler); final InetSocketAddress deviceAddress = InetSocketAddress.createUnresolved("yahoo", 42); Mockito.when(connection.getRemoteAddress()).thenReturn(deviceAddress); diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java index e7efddeb35..846f504e38 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java @@ -24,14 +24,11 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import io.netty.util.HashedWheelTimer; -import io.netty.util.Timeout; import java.math.BigInteger; import java.util.concurrent.atomic.AtomicLong; 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.runners.MockitoJUnitRunner; @@ -50,7 +47,6 @@ 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.MessageTranslator; import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary; @@ -103,10 +99,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731 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.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.Notification; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -151,8 +145,6 @@ public class DeviceContextImplTest { @Mock TranslatorLibrary translatorLibrary; @Mock - Registration registration; - @Mock MessageTranslator messageTranslatorPacketReceived; @Mock MessageTranslator messageTranslatorFlowCapableNodeConnector; @@ -161,14 +153,10 @@ public class DeviceContextImplTest { @Mock private DeviceInfo deviceInfo; @Mock - private DeviceManager deviceManager; - @Mock private ConvertorExecutor convertorExecutor; @Mock private MessageSpy messageSpy; - private InOrder inOrderDevState; - private final AtomicLong atomicLong = new AtomicLong(0); private DeviceContext deviceContextSpy; @@ -220,10 +208,10 @@ public class DeviceContextImplTest { dataBroker, messageSpy, translatorLibrary, - deviceManager, convertorExecutor, false, timer, false, - DeviceInitializerProviderFactory.createDefaultProvider()); + DeviceInitializerProviderFactory.createDefaultProvider(), + true, false); ((DeviceContextImpl) deviceContext).lazyTransactionManagerInitialization(); deviceContextSpy = Mockito.spy(deviceContext); @@ -362,14 +350,6 @@ public class DeviceContextImplTest { assertEquals(translatorLibrary, pickedTranslatorLibrary); } - @Test - public void testBarrierFieldSetGet() { - final Timeout mockedTimeout = mock(Timeout.class); - deviceContext.setCurrentBarrierTimeout(mockedTimeout); - final Timeout pickedBarrierTimeout = deviceContext.getBarrierTaskTimeout(); - assertEquals(mockedTimeout, pickedBarrierTimeout); - } - @Test public void testGetMessageSpy() { final MessageSpy pickedMessageSpy = deviceContext.getMessageSpy(); @@ -436,17 +416,10 @@ public class DeviceContextImplTest { .child(Table.class, new TableKey((short) 0)) .child(Flow.class, new FlowKey(new FlowId("ut-ofp:f456"))); - Mockito.when(deviceManager.isFlowRemovedNotificationOn()).thenReturn(true); - deviceContext.setNotificationPublishService(mockedNotificationPublishService); deviceContext.processFlowRemovedMessage(flowRemovedBld.build()); Mockito.verify(itemLifecycleListener).onRemoved(flowToBeRemovedPath); - - Mockito.when(deviceManager.isFlowRemovedNotificationOn()).thenReturn(false); - deviceContext.processFlowRemovedMessage(flowRemovedBld.build()); - - Mockito.verify(mockedNotificationPublishService).offerNotification(Matchers.any(Notification.class)); } @Test diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java index 431e7b2f1c..47a637952a 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java @@ -40,13 +40,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; 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.CapabilitiesV10; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint16Type; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint32Type; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder; @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; + private static final long barrierIntervalNanos = 500; private static final NodeId DUMMY_NODE_ID = new NodeId("dummyNodeId"); @Mock @@ -95,20 +98,20 @@ public class DeviceManagerImplTest { when(mockedWriteTransaction.submit()).thenReturn(mockedFuture); final DeviceManagerImpl deviceManager = new DeviceManagerImpl( + new OpenflowProviderConfigBuilder() + .setBarrierCountLimit(new NonZeroUint16Type(barrierCountLimit)) + .setBarrierIntervalTimeoutLimit(new NonZeroUint32Type(barrierIntervalNanos)) + .setGlobalNotificationQuota(TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA) + .setSwitchFeaturesMandatory(false) + .setEnableFlowRemovedNotification(true) + .setSkipTableFeatures(false) + .build(), mockedDataBroker, messageIntelligenceAgency, null, new HashedWheelTimer(), convertorExecutor, - DeviceInitializerProviderFactory.createDefaultProvider(), - false); - - deviceManager.setBarrierCountLimit(barrierCountLimit); - deviceManager.setBarrierInterval(barrierIntervalNanos); - deviceManager.setGlobalNotificationQuota(TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA); - deviceManager.setSwitchFeaturesMandatory(false); - deviceManager.setFlowRemovedNotificationOn(true); - deviceManager.setSkipTableFeatures(false); + DeviceInitializerProviderFactory.createDefaultProvider()); return deviceManager; } diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImplTest.java index 4fade11b22..86ed96dec2 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImplTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImplTest.java @@ -17,6 +17,8 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration; +import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration; import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext; @@ -55,6 +57,10 @@ public class ContextChainHolderImplTest { private ExecutorService executorService; @Mock private ClusterSingletonServiceRegistration clusterSingletonServiceRegistration; + @Mock + private EntityOwnershipService entityOwnershipService; + @Mock + private EntityOwnershipListenerRegistration entityOwnershipListenerRegistration; private ContextChainHolderImpl contextChainHolder; @@ -78,11 +84,13 @@ public class ContextChainHolderImplTest { Mockito.when(singletonServicesProvider.registerClusterSingletonService(Mockito.any())) .thenReturn(clusterSingletonServiceRegistration); - contextChainHolder = new ContextChainHolderImpl(timer, executorService); + Mockito.when(entityOwnershipService.registerListener(Mockito.any(), Mockito.any())) + .thenReturn(entityOwnershipListenerRegistration); + + contextChainHolder = new ContextChainHolderImpl(timer, executorService, singletonServicesProvider, entityOwnershipService); contextChainHolder.addManager(statisticsManager); contextChainHolder.addManager(rpcManager); contextChainHolder.addManager(deviceManager); - contextChainHolder.addSingletonServicesProvider(singletonServicesProvider); } @Test diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImplTest.java index 9a5b82cf18..3f68647244 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImplTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImplTest.java @@ -39,6 +39,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N 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.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint16Type; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.opendaylight.yangtools.yang.binding.RpcService; @@ -86,8 +88,9 @@ public class RpcManagerImplTest { @Before public void setUp() { final NodeKey nodeKey = new NodeKey(nodeId); - rpcManager = new RpcManagerImpl(rpcProviderRegistry, extensionConverterProvider, convertorExecutor, notificationPublishService); - rpcManager.setRpcRequestQuota(QUOTA_VALUE); + rpcManager = new RpcManagerImpl(new OpenflowProviderConfigBuilder() + .setRpcRequestsQuota(new NonZeroUint16Type(QUOTA_VALUE)) + .build(), rpcProviderRegistry, extensionConverterProvider, convertorExecutor, notificationPublishService); GetFeaturesOutput featuresOutput = new GetFeaturesOutputBuilder() .setVersion(OFConstants.OFP_VERSION_1_3) diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImplTest.java index c8edc28bc5..ebf9396c3d 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImplTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImplTest.java @@ -57,6 +57,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N 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.MultipartReply; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint32Type; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.sm.control.rev150812.ChangeStatisticsWorkModeInputBuilder; 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; @@ -151,11 +153,14 @@ public class StatisticsManagerImplTest { final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager(); final long basicTimerDelay = 3000L; final long maximumTimerDelay = 900000L; - statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, new HashedWheelTimer(), + + statisticsManager = new StatisticsManagerImpl( + new OpenflowProviderConfigBuilder() + .setBasicTimerDelay(new NonZeroUint32Type(basicTimerDelay)) + .setMaximumTimerDelay(new NonZeroUint32Type(maximumTimerDelay)) + .setIsStatisticsPollingOn(false) + .build(), rpcProviderRegistry, new HashedWheelTimer(), convertorManager); - statisticsManager.setBasicTimerDelay(basicTimerDelay); - statisticsManager.setMaximumTimerDelay(maximumTimerDelay); - statisticsManager.setIsStatisticsPollingOn(false); } private static Map getContextsMap(final StatisticsManagerImpl statisticsManager)