Convert SouthboundProvider into a component 09/104409/10
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 15 Feb 2023 17:28:13 +0000 (18:28 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 24 Jan 2024 12:29:00 +0000 (13:29 +0100)
Use Declarative Services to wire SouthboundProvider, which allows us to
ditch Blueprint and have much saner layout.

JIRA: OVSDB-468
Change-Id: Ie43b9e33865a4a643ae5baeccc56cea0b0a73fc5
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
southbound/southbound-impl/pom.xml
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProvider.java
southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProviderConfigurator.java [deleted file]
southbound/southbound-impl/src/main/resources/OSGI-INF/blueprint/southbound.xml [deleted file]
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/SouthboundProviderTest.java

index a3378999e28ffee0fde1d89ea9e3bcbab64fd9ea..6afdb06afe998ad1ae9d010be2dfbd676a4ec664 100644 (file)
@@ -107,6 +107,14 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>jakarta.annotation-api</artifactId>
       <optional>true</optional>
     </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.service.component.annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.service.metatype.annotations</artifactId>
+    </dependency>
 
     <!-- testing dependencies -->
     <dependency>
index 540a64064ffc103c5eec3fbe8eae91c48b82e44e..b4f2c815ad56e5e91ff3b5d1e91e86ed7daa9860 100644 (file)
@@ -10,12 +10,10 @@ package org.opendaylight.ovsdb.southbound;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.util.concurrent.FluentFuture;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.AtomicBoolean;
-import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -47,11 +45,31 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
+@Component(service = { }, configurationPid = "org.opendaylight.ovsdb.southbound")
+@Designate(ocd = SouthboundProvider.Configuration.class)
+// non-final for testing
 public class SouthboundProvider implements ClusteredDataTreeChangeListener<Topology>, AutoCloseable {
+    @ObjectClassDefinition
+    public @interface Configuration {
+        @AttributeDefinition
+        boolean skip$_$monitoring$_$manager$_$status() default false;
+        @AttributeDefinition
+        String[] bridge$_$reconciliation$_$inclusion$_$list();
+        @AttributeDefinition
+        String[] bridge$_$reconciliation$_$exclusion$_$list();
+    }
+
     private static final Logger LOG = LoggerFactory.getLogger(SouthboundProvider.class);
     private static final String ENTITY_TYPE = "ovsdb-southbound-provider";
 
@@ -59,28 +77,43 @@ public class SouthboundProvider implements ClusteredDataTreeChangeListener<Topol
     @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
     private static DataBroker db;
     // FIXME: get rid of this static
-    private static List<String> reconcileBridgeInclusionList = new ArrayList<>();
+    private static List<String> reconcileBridgeInclusionList = List.of();
     // FIXME: get rid of this static
-    private static List<String> reconcileBridgeExclusionList = new ArrayList<>();
+    private static List<String> reconcileBridgeExclusionList = List.of();
 
     public static DataBroker getDb() {
         return db;
     }
 
-    private OvsdbConnectionManager cm;
-    private TransactionInvoker txInvoker;
-    private OvsdbDataTreeChangeListener ovsdbDataTreeChangeListener;
-    private OvsdbOperGlobalListener ovsdbOperGlobalListener;
+    public static List<String> getBridgesReconciliationInclusionList() {
+        return reconcileBridgeInclusionList;
+    }
+
+    public static List<String> getBridgesReconciliationExclusionList() {
+        return reconcileBridgeExclusionList;
+    }
+
+    @VisibleForTesting
+    @SuppressFBWarnings("EI_EXPOSE_STATIC_REP2")
+    public static void setBridgesReconciliationInclusionList(final List<String> list) {
+        reconcileBridgeInclusionList = list;
+    }
+
+    private final OvsdbConnectionManager cm;
+    private final TransactionInvoker txInvoker;
+    private final OvsdbDataTreeChangeListener ovsdbDataTreeChangeListener;
+    private final OvsdbOperGlobalListener ovsdbOperGlobalListener;
     private final EntityOwnershipService entityOwnershipService;
-    private EntityOwnershipCandidateRegistration registration;
-    private SouthboundPluginInstanceEntityOwnershipListener providerOwnershipChangeListener;
+    private final SouthboundPluginInstanceEntityOwnershipListener providerOwnershipChangeListener;
     private final OvsdbConnection ovsdbConnection;
     private final InstanceIdentifierCodec instanceIdentifierCodec;
     private final SystemReadyMonitor systemReadyMonitor;
     private final AtomicBoolean registered = new AtomicBoolean(false);
-    private ListenerRegistration<SouthboundProvider> operTopologyRegistration;
     private final OvsdbDiagStatusProvider ovsdbStatusProvider;
 
+    private EntityOwnershipCandidateRegistration registration;
+    private ListenerRegistration<SouthboundProvider> operTopologyRegistration;
+
     @Inject
     public SouthboundProvider(final DataBroker dataBroker,
                               final EntityOwnershipService entityOwnershipServiceDependency,
@@ -89,7 +122,50 @@ public class SouthboundProvider implements ClusteredDataTreeChangeListener<Topol
                               final BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer,
                               final SystemReadyMonitor systemReadyMonitor,
                               final DiagStatusService diagStatusService) {
-        SouthboundProvider.db = dataBroker;
+        this(dataBroker, entityOwnershipServiceDependency, ovsdbConnection, schemaService,
+            bindingNormalizedNodeSerializer, systemReadyMonitor, diagStatusService, false, List.of(), List.of());
+    }
+
+    @Activate
+    public SouthboundProvider(@Reference final DataBroker dataBroker,
+                              @Reference final EntityOwnershipService entityOwnershipServiceDependency,
+                              @Reference final OvsdbConnection ovsdbConnection,
+                              @Reference final DOMSchemaService schemaService,
+                              @Reference final BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer,
+                              @Reference final SystemReadyMonitor systemReadyMonitor,
+                              @Reference final DiagStatusService diagStatusService,
+                              final Configuration configuration) {
+        this(dataBroker, entityOwnershipServiceDependency, ovsdbConnection, schemaService,
+            bindingNormalizedNodeSerializer, systemReadyMonitor, diagStatusService,
+            configuration.skip$_$monitoring$_$manager$_$status(),
+            List.of(configuration.bridge$_$reconciliation$_$inclusion$_$list()),
+            List.of(configuration.bridge$_$reconciliation$_$exclusion$_$list()));
+    }
+
+    @SuppressFBWarnings(
+        value = { "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD" },
+        justification = "This is not a final class due to deep mocking. There is a FIXME for the static wiring above")
+    public SouthboundProvider(final DataBroker dataBroker,
+                              final EntityOwnershipService entityOwnershipServiceDependency,
+                              final OvsdbConnection ovsdbConnection,
+                              final DOMSchemaService schemaService,
+                              final BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer,
+                              final SystemReadyMonitor systemReadyMonitor,
+                              final DiagStatusService diagStatusService,
+                              final boolean skipMonitoringManagerStatus,
+                              final List<String> bridgeReconciliationInclusions,
+                              final List<String> bridgeReconciliationExclusions) {
+        // FIXME: get rid of this static wiring
+        db = dataBroker;
+        reconcileBridgeInclusionList = bridgeReconciliationInclusions;
+        reconcileBridgeExclusionList = bridgeReconciliationExclusions;
+        LOG.debug("skipManagerStatus set to {}", skipMonitoringManagerStatus);
+        if (skipMonitoringManagerStatus) {
+            SouthboundConstants.SKIP_COLUMN_FROM_TABLE.get("Manager").add("status");
+        } else {
+            SouthboundConstants.SKIP_COLUMN_FROM_TABLE.get("Manager").remove("status");
+        }
+
         entityOwnershipService = entityOwnershipServiceDependency;
         registration = null;
         this.ovsdbConnection = ovsdbConnection;
@@ -97,20 +173,13 @@ public class SouthboundProvider implements ClusteredDataTreeChangeListener<Topol
         instanceIdentifierCodec = new InstanceIdentifierCodec(schemaService, bindingNormalizedNodeSerializer);
         this.systemReadyMonitor = systemReadyMonitor;
         LOG.info("SouthboundProvider ovsdbConnectionService Initialized");
-    }
 
-    /**
-     * Used by blueprint when starting the container.
-     */
-    @PostConstruct
-    public void init() {
-        LOG.info("SouthboundProvider Session Initiated");
         ovsdbStatusProvider.reportStatus(ServiceState.STARTING, "OVSDB initialization in progress");
-        txInvoker = new TransactionInvokerImpl(db);
-        cm = new OvsdbConnectionManager(db, txInvoker, entityOwnershipService, ovsdbConnection,
+        txInvoker = new TransactionInvokerImpl(dataBroker);
+        cm = new OvsdbConnectionManager(dataBroker, txInvoker, entityOwnershipService, ovsdbConnection,
                 instanceIdentifierCodec);
-        ovsdbDataTreeChangeListener = new OvsdbDataTreeChangeListener(db, cm, instanceIdentifierCodec);
-        ovsdbOperGlobalListener = new OvsdbOperGlobalListener(db, cm, txInvoker);
+        ovsdbDataTreeChangeListener = new OvsdbDataTreeChangeListener(dataBroker, cm, instanceIdentifierCodec);
+        ovsdbOperGlobalListener = new OvsdbOperGlobalListener(dataBroker, cm, txInvoker);
 
         //Register listener for entityOnwership changes
         providerOwnershipChangeListener =
@@ -121,8 +190,8 @@ public class SouthboundProvider implements ClusteredDataTreeChangeListener<Topol
         try {
             registration = entityOwnershipService.registerCandidate(instanceEntity);
         } catch (CandidateAlreadyRegisteredException e) {
-            LOG.warn("OVSDB Southbound Provider instance entity {} was already "
-                    + "registered for ownership", instanceEntity, e);
+            LOG.warn("OVSDB Southbound Provider instance entity {} was already registered for ownership",
+                instanceEntity, e);
         }
         InstanceIdentifier<Topology> path = InstanceIdentifier
                 .create(NetworkTopology.class)
@@ -131,11 +200,13 @@ public class SouthboundProvider implements ClusteredDataTreeChangeListener<Topol
                 DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, path);
 
         LOG.trace("Registering listener for path {}", treeId);
-        operTopologyRegistration = db.registerDataTreeChangeListener(treeId, this);
+        operTopologyRegistration = dataBroker.registerDataTreeChangeListener(treeId, this);
+        LOG.info("SouthboundProvider Session Initiated");
     }
 
-    @Override
     @PreDestroy
+    @Deactivate
+    @Override
     public void close() {
         LOG.info("SouthboundProvider Closed");
         try {
@@ -228,33 +299,6 @@ public class SouthboundProvider implements ClusteredDataTreeChangeListener<Topol
         }
     }
 
-    public void setSkipMonitoringManagerStatus(final boolean flag) {
-        LOG.debug("skipManagerStatus set to {}", flag);
-        if (flag) {
-            SouthboundConstants.SKIP_COLUMN_FROM_TABLE.get("Manager").add("status");
-        } else {
-            SouthboundConstants.SKIP_COLUMN_FROM_TABLE.get("Manager").remove("status");
-        }
-    }
-
-    @SuppressFBWarnings("EI_EXPOSE_STATIC_REP2")
-    public static void setBridgesReconciliationInclusionList(final List<String> bridgeList) {
-        reconcileBridgeInclusionList = bridgeList;
-    }
-
-    @SuppressFBWarnings("EI_EXPOSE_STATIC_REP2")
-    public static void setBridgesReconciliationExclusionList(final List<String> bridgeList) {
-        reconcileBridgeExclusionList = bridgeList;
-    }
-
-    public static List<String> getBridgesReconciliationInclusionList() {
-        return reconcileBridgeInclusionList;
-    }
-
-    public static List<String> getBridgesReconciliationExclusionList() {
-        return reconcileBridgeExclusionList;
-    }
-
     @VisibleForTesting
     boolean isRegistered() {
         return registered.get();
diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProviderConfigurator.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/SouthboundProviderConfigurator.java
deleted file mode 100644 (file)
index 2b098eb..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2019 Red Hat, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.ovsdb.southbound;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Helper to let Blueprint XML configure {@link SouthboundProvider}.
- *
- * @author Michael Vorburger.ch
- */
-public class SouthboundProviderConfigurator {
-
-    private static final Logger LOG = LoggerFactory.getLogger(SouthboundProviderConfigurator.class);
-
-    private static final String SKIP_MONITORING_MANAGER_STATUS_PARAM = "skip-monitoring-manager-status";
-    private static final String BRIDGES_RECONCILIATION_INCLUSION_LIST_PARAM = "bridges-reconciliation-inclusion-list";
-    private static final String BRIDGES_RECONCILIATION_EXCLUSION_LIST_PARAM = "bridges-reconciliation-exclusion-list";
-
-    private final SouthboundProvider southboundProvider;
-
-    public SouthboundProviderConfigurator(SouthboundProvider southboundProvider) {
-        this.southboundProvider = southboundProvider;
-    }
-
-    public void setSkipMonitoringManagerStatus(boolean flag) {
-        southboundProvider.setSkipMonitoringManagerStatus(flag);
-    }
-
-    public void setBridgesReconciliationInclusionList(String bridgeListStr) {
-        if (bridgeListStr != null && !bridgeListStr.equals("")) {
-            SouthboundProvider.setBridgesReconciliationInclusionList(getBridgesList(bridgeListStr));
-        }
-    }
-
-    public void setBridgesReconciliationExclusionList(String bridgeListStr) {
-        if (bridgeListStr != null && !bridgeListStr.equals("")) {
-            SouthboundProvider.setBridgesReconciliationExclusionList(getBridgesList(bridgeListStr));
-        }
-    }
-
-    private static List<String> getBridgesList(final String bridgeListStr) {
-        List<String> bridgeList = new ArrayList<>();
-        StringTokenizer tokenizer = new StringTokenizer(bridgeListStr, ",");
-        while (tokenizer.hasMoreTokens()) {
-            bridgeList.add(tokenizer.nextToken());
-        }
-        return bridgeList;
-
-    }
-
-    public void updateConfigParameter(Map<String, Object> configParameters) {
-        if (configParameters != null && !configParameters.isEmpty()) {
-            LOG.debug("Config parameters received : {}", configParameters.entrySet());
-            for (Map.Entry<String, Object> paramEntry : configParameters.entrySet()) {
-                if (paramEntry.getKey().equalsIgnoreCase(SKIP_MONITORING_MANAGER_STATUS_PARAM)) {
-                    southboundProvider
-                            .setSkipMonitoringManagerStatus(Boolean.parseBoolean((String) paramEntry.getValue()));
-                } else if (paramEntry.getKey().equalsIgnoreCase(BRIDGES_RECONCILIATION_INCLUSION_LIST_PARAM)) {
-                    String bridgeListStr = (String)paramEntry.getValue();
-                    if (bridgeListStr != null && !bridgeListStr.equals("")) {
-                        SouthboundProvider.setBridgesReconciliationInclusionList(getBridgesList(bridgeListStr));
-                    }
-                } else if (paramEntry.getKey().equalsIgnoreCase(BRIDGES_RECONCILIATION_EXCLUSION_LIST_PARAM)) {
-                    String bridgeListStr = (String)paramEntry.getValue();
-                    if (bridgeListStr != null && !bridgeListStr.equals("")) {
-                        SouthboundProvider.setBridgesReconciliationExclusionList(getBridgesList(bridgeListStr));
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/southbound/southbound-impl/src/main/resources/OSGI-INF/blueprint/southbound.xml b/southbound/southbound-impl/src/main/resources/OSGI-INF/blueprint/southbound.xml
deleted file mode 100644 (file)
index 04f822b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
-  xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
-
-    <cm:property-placeholder persistent-id="org.opendaylight.ovsdb.southbound" update-strategy="none">
-    <cm:default-properties>
-      <cm:property name="skip-monitoring-manager-status" value="false"/>
-      <cm:property name="bridge-reconciliation-inclusion-list" value=""/>
-      <cm:property name="bridge-reconciliation-exclusion-list" value=""/>
-    </cm:default-properties>
-  </cm:property-placeholder>
-
-  <bean id="southboundProviderConfigurator"
-    class="org.opendaylight.ovsdb.southbound.SouthboundProviderConfigurator">
-   <cm:managed-properties persistent-id="org.opendaylight.ovsdb.southbound"
-                           update-strategy="component-managed"
-                           update-method="updateConfigParameter"/>
-    <argument ref="southboundProvider" />
-    <property name="skipMonitoringManagerStatus" value="${skip-monitoring-manager-status}"/>
-    <property name="bridgesReconciliationInclusionList" value="${bridge-reconciliation-inclusion-list}"/>
-    <property name="bridgesReconciliationExclusionList" value="${bridge-reconciliation-exclusion-list}"/>
-  </bean>
-
-  <reference id="diagStatusService" interface="org.opendaylight.infrautils.diagstatus.DiagStatusService"/>
-  <reference id="systemReadyMonitor" interface="org.opendaylight.infrautils.ready.SystemReadyMonitor"/>
-  <reference id="dataBroker" interface="org.opendaylight.mdsal.binding.api.DataBroker"/>
-  <reference id="bindingNormalizedNodeSerializer" interface="org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer"/>
-  <reference id="domSchemaService" interface="org.opendaylight.mdsal.dom.api.DOMSchemaService"/>
-  <reference id="entityOwnershipService" interface="org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService"/>
-  <reference id="ovsdbConnection" interface="org.opendaylight.ovsdb.lib.OvsdbConnection"/>
-
-  <bean id="southboundProvider" class="org.opendaylight.ovsdb.southbound.SouthboundProvider" init-method="init" destroy-method="close">
-    <argument ref="dataBroker"/>
-    <argument ref="entityOwnershipService"/>
-    <argument ref="ovsdbConnection"/>
-    <argument ref="domSchemaService"/>
-    <argument ref="bindingNormalizedNodeSerializer"/>
-    <argument ref="systemReadyMonitor"/>
-    <argument ref="diagStatusService"/>
-  </bean>
-
-</blueprint>
index bc97d8a411b96a66cc1adc6602fb723e72ca64d8..2e440e12b261e869a8bfc521eb4d939c77c2f5ce 100644 (file)
@@ -83,9 +83,6 @@ public class SouthboundProviderTest extends AbstractConcurrentDataBrokerTest {
                 new TestSystemReadyMonitor(IMMEDIATE),
                 diagStatusService)) {
 
-            // Initiate the session
-            southboundProvider.init();
-
             // Verify that at least one listener was registered
             verify(entityOwnershipService, atLeastOnce()).registerListener(
                     anyString(), any(EntityOwnershipListener.class));
@@ -110,9 +107,6 @@ public class SouthboundProviderTest extends AbstractConcurrentDataBrokerTest {
                 new TestSystemReadyMonitor(IMMEDIATE),
                 diagStatusService)) {
 
-            // Initiate the session
-            southboundProvider.init();
-
             // Verify that at least one listener was registered
             verify(entityOwnershipService, atLeastOnce()).registerListener(
                     anyString(), any(EntityOwnershipListener.class));
@@ -139,8 +133,6 @@ public class SouthboundProviderTest extends AbstractConcurrentDataBrokerTest {
                 new TestSystemReadyMonitor(IMMEDIATE),
                 diagStatusService)) {
 
-            southboundProvider.init();
-
             assertEquals(getDataBroker(), SouthboundProvider.getDb());
         }
     }
@@ -163,8 +155,6 @@ public class SouthboundProviderTest extends AbstractConcurrentDataBrokerTest {
                 new TestSystemReadyMonitor(IMMEDIATE),
                 diagStatusService)) {
 
-            southboundProvider.init();
-
             // At this point the OVSDB topology must not be present in either tree
             assertFalse(getDataBroker().newReadOnlyTransaction().read(LogicalDatastoreType.CONFIGURATION,
                     topologyIid).get().isPresent());