Eliminate AlarmAgent 17/110217/1
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 11 Feb 2024 21:18:03 +0000 (22:18 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 11 Feb 2024 21:19:14 +0000 (22:19 +0100)
AlarmAgent is a rather useless indirection for invoking MBean
operations. Integrate its functionality into ReconciliationServiceImpl,
which makes it clear it is not just a CLI component.

JIRA: OPNFLWPLUG-1112
Change-Id: I775fab6d462daeccea611b39108b74a80063ea16
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/ReconciliationServiceImpl.java
applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/AlarmAgent.java [deleted file]
applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/NodeReconciliationAlarm.java
applications/southbound-cli/src/main/resources/OSGI-INF/blueprint/southbound-cli.xml

index f09f748fd90dea53ce32c44808716e442c0b414d..0f8faf05030bf8f6149cf303480a4c6862dd28ba 100644 (file)
@@ -15,6 +15,7 @@ import static org.opendaylight.openflowplugin.api.openflow.ReconciliationState.R
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
+import java.lang.management.ManagementFactory;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.util.Date;
@@ -26,6 +27,13 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.stream.Collectors;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
@@ -33,7 +41,7 @@ import org.opendaylight.openflowplugin.api.openflow.FlowGroupCacheManager;
 import org.opendaylight.openflowplugin.api.openflow.ReconciliationState;
 import org.opendaylight.openflowplugin.applications.frm.FlowNodeReconciliation;
 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
-import org.opendaylight.openflowplugin.applications.southboundcli.alarm.AlarmAgent;
+import org.opendaylight.openflowplugin.applications.southboundcli.alarm.NodeReconciliationAlarm;
 import org.opendaylight.openflowplugin.applications.southboundcli.util.OFNode;
 import org.opendaylight.openflowplugin.applications.southboundcli.util.ShellUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
@@ -60,29 +68,59 @@ import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class ReconciliationServiceImpl implements ReconciliationService, AutoCloseable {
+// FIXME: this is not just a CLI component, it should live somewhere else
+public final class ReconciliationServiceImpl implements ReconciliationService, AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(ReconciliationServiceImpl.class);
+    private static final ObjectName ALARM_NAME;
 
+    static {
+        try {
+            ALARM_NAME = new ObjectName("SDNC.FM:name=NodeReconciliationOperationOngoingBean");
+        } catch (MalformedObjectNameException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    private final NodeReconciliationAlarm alarm = new NodeReconciliationAlarm();
     private final DataBroker broker;
     private final FlowNodeReconciliation flowNodeReconciliation;
-    private final AlarmAgent alarmAgent;
     private final NodeListener nodeListener;
     private final Map<String, ReconciliationState> reconciliationStates;
 
     private ExecutorService executor = Executors.newWorkStealingPool(10);
+    private boolean unregister;
 
     public ReconciliationServiceImpl(final DataBroker broker, final ForwardingRulesManager frm,
-            final AlarmAgent alarmAgent, final NodeListener nodeListener,
-            final FlowGroupCacheManager flowGroupCacheManager) {
+            final NodeListener nodeListener, final FlowGroupCacheManager flowGroupCacheManager) {
         this.broker = requireNonNull(broker);
         flowNodeReconciliation = frm.getFlowNodeReconciliation();
-        this.alarmAgent = requireNonNull(alarmAgent);
         this.nodeListener = requireNonNull(nodeListener);
         reconciliationStates = flowGroupCacheManager.getReconciliationStates();
+
+        unregister = false;
+        final var mbs = ManagementFactory.getPlatformMBeanServer();
+        if (!mbs.isRegistered(ALARM_NAME)) {
+            try {
+                mbs.registerMBean(alarm, ALARM_NAME);
+                unregister = true;
+                LOG.info("Registered Mbean {} successfully", ALARM_NAME);
+            } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
+                LOG.error("Registeration failed for Mbean {}", ALARM_NAME, e);
+            }
+        }
     }
 
     @Override
     public void close() {
+        if (unregister) {
+            unregister = false;
+            try {
+                ManagementFactory.getPlatformMBeanServer().unregisterMBean(ALARM_NAME);
+            } catch (MBeanRegistrationException | InstanceNotFoundException e) {
+                LOG.error("Unregisteration failed for Mbean {}", ALARM_NAME, e);
+            }
+        }
+
         if (executor != null) {
             executor.shutdownNow();
             executor = null;
@@ -120,11 +158,14 @@ public class ReconciliationServiceImpl implements ReconciliationService, AutoClo
                 if (state != null && state.getState().equals(STARTED)) {
                     inprogressNodes.add(Uint64.valueOf(nodeId));
                 } else {
-                    alarmAgent.raiseNodeReconciliationAlarm(nodeId);
+                    final var alarmText = getAlarmText(nodeId,  " started reconciliation");
+                    final var source = getSourceText(nodeId);
+                    LOG.debug("Raising NodeReconciliationOperationOngoing alarm, alarmText {} source {}", alarmText,
+                        source);
+                    alarm.raiseAlarm("NodeReconciliationOperationOngoing", alarmText, source);
                     LOG.info("Executing reconciliation for node {} with state ", nodeId);
                     NodeKey nodeKey = new NodeKey(new NodeId("openflow:" + nodeId));
-                    ReconciliationTask reconcileTask = new ReconciliationTask(Uint64.valueOf(nodeId), nodeKey);
-                    executor.execute(reconcileTask);
+                    executor.execute(new ReconciliationTask(Uint64.valueOf(nodeId), nodeKey));
                 }
             });
             ReconcileOutput reconcilingInProgress = new ReconcileOutputBuilder()
@@ -155,6 +196,25 @@ public class ReconciliationServiceImpl implements ReconciliationService, AutoClo
         return nodes;
     }
 
+    /**
+     * Method gets the alarm text for the nodeId.
+     *
+     * @param nodeId Source of the alarm nodeId
+     * @param event reason for alarm invoke/clear
+     */
+    private static @NonNull String getAlarmText(final Long nodeId, final String event) {
+        return "OF Switch " + nodeId + event;
+    }
+
+    /**
+     * Method gets the source text for the nodeId.
+     *
+     * @param nodeId Source of the alarm nodeId
+     */
+    private static String getSourceText(final Long nodeId) {
+        return "Dpn=" + nodeId;
+    }
+
     private final class ReconciliationTask implements Runnable {
         private static final String DATE_AND_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
         private final NodeKey nodeKey;
@@ -187,7 +247,11 @@ public class ReconciliationServiceImpl implements ReconciliationService, AutoClo
                 updateReconciliationState(FAILED);
                 LOG.error("Error occurred while invoking reconcile RPC for node {}", nodeId, e);
             } finally {
-                alarmAgent.clearNodeReconciliationAlarm(nodeId.longValue());
+                final var dpnId = nodeId.longValue();
+                final var alarmText = getAlarmText(dpnId, " finished reconciliation");
+                final var source = getSourceText(dpnId);
+                LOG.debug("Clearing NodeReconciliationOperationOngoing alarm of source {}", source);
+                alarm.clearAlarm("NodeReconciliationOperationOngoing", alarmText, source);
             }
         }
 
@@ -238,8 +302,7 @@ public class ReconciliationServiceImpl implements ReconciliationService, AutoClo
         }
 
         private void updateReconciliationState(final ReconciliationState.ReconciliationStatus status) {
-            ReconciliationState state = new ReconciliationState(status, LocalDateTime.now());
-            reconciliationStates.put(nodeId.toString(),state);
+            reconciliationStates.put(nodeId.toString(), new ReconciliationState(status, LocalDateTime.now()));
         }
     }
 }
diff --git a/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/AlarmAgent.java b/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/AlarmAgent.java
deleted file mode 100644 (file)
index 5f20a88..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.openflowplugin.applications.southboundcli.alarm;
-
-import java.lang.management.ManagementFactory;
-import javax.annotation.PostConstruct;
-import javax.inject.Singleton;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanException;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Singleton
-public class AlarmAgent {
-    private static final Logger LOG = LoggerFactory.getLogger(AlarmAgent.class);
-    private static final String BEAN_NAME = "SDNC.FM:name=NodeReconciliationOperationOngoingBean";
-    private final MBeanServer mbs;
-    private final NodeReconciliationAlarm alarmBean = new NodeReconciliationAlarm();
-    private ObjectName alarmName;
-
-    /**
-     * constructor get the instance of platform MBeanServer.
-     */
-    public AlarmAgent() {
-        mbs = ManagementFactory.getPlatformMBeanServer();
-    }
-
-    @PostConstruct
-    public void start() {
-        try {
-            alarmName = new ObjectName(BEAN_NAME);
-            if (!mbs.isRegistered(alarmName)) {
-                mbs.registerMBean(alarmBean, alarmName);
-                LOG.info("Registered Mbean {} successfully", alarmName);
-            }
-        } catch (MalformedObjectNameException e) {
-            LOG.error("ObjectName instance creation failed for bean {}", BEAN_NAME, e);
-        } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
-            LOG.error("Registeration failed for Mbean {}", alarmName, e);
-        }
-    }
-
-    /**
-     * Method invoke raise alarm JMX API in platform MbeanServer with alarm
-     * details.
-     *
-     * @param alarmId alarm to be raised
-     * @param text Additional details describing about the alarm on which dpnId
-     * @param src Source of the alarm ex: dpnId=openflow:1 the source node that
-     *            caused this alarm
-     */
-    public void invokeFMRaiseMethod(final String alarmId, final String text, final String src) {
-        try {
-            mbs.invoke(alarmName, "raiseAlarm", new Object[] { alarmId, text, src },
-                    new String[] { String.class.getName(), String.class.getName(), String.class.getName() });
-            LOG.debug("Invoked raiseAlarm function for Mbean {} with source {}", BEAN_NAME, src);
-        } catch (InstanceNotFoundException | ReflectionException | MBeanException e) {
-            LOG.error("Invoking raiseAlarm function failed for Mbean {}", alarmName, e);
-        }
-    }
-
-    /**
-     * Method invoke clear alarm JMX API in platform MbeanServer with alarm
-     * details.
-     *
-     * @param alarmId alarm to be cleared
-     * @param text Additional details describing about the alarm on which dpnId
-     * @param src Source of the alarm ex: dpn=openflow:1 the source node that
-     *            caused this alarm
-     */
-    public void invokeFMClearMethod(final String alarmId, final String text, final String src) {
-        try {
-            mbs.invoke(alarmName, "clearAlarm", new Object[] { alarmId, text, src },
-                    new String[] { String.class.getName(), String.class.getName(), String.class.getName() });
-            LOG.debug("Invoked clearAlarm function for Mbean {} with source {}", BEAN_NAME, src);
-        } catch (InstanceNotFoundException | ReflectionException | MBeanException e) {
-            LOG.error("Invoking clearAlarm method failed for Mbean {}", alarmName, e);
-        }
-    }
-
-    /**
-     * Method gets the alarm details to be raised and construct the alarm
-     * objects.
-     *
-     * @param nodeId Source of the alarm dpnId
-     */
-    public void raiseNodeReconciliationAlarm(final Long nodeId) {
-        String alarmText = getAlarmText(nodeId,  " started reconciliation");
-        String source = getSourceText(nodeId);
-
-        LOG.debug("Raising NodeReconciliationOperationOngoing alarm, alarmText {} source {}", alarmText, source);
-        // Invokes JMX raiseAlarm method
-        invokeFMRaiseMethod("NodeReconciliationOperationOngoing", alarmText, source);
-    }
-
-    /**
-     * Method gets the alarm details to be cleared and construct the alarm
-     * objects.
-     *
-     * @param nodeId Source of the alarm dpnId
-     */
-    public void clearNodeReconciliationAlarm(final Long nodeId) {
-        String alarmText = getAlarmText(nodeId, " finished reconciliation");
-        String source = getSourceText(nodeId);
-
-        LOG.debug("Clearing NodeReconciliationOperationOngoing alarm of source {}", source);
-        // Invokes JMX clearAlarm method
-        invokeFMClearMethod("NodeReconciliationOperationOngoing", alarmText, source);
-    }
-
-    /**
-     * Method gets the alarm text for the nodeId.
-     *
-     * @param nodeId Source of the alarm nodeId
-     * @param event reason for alarm invoke/clear
-     */
-    private static String getAlarmText(final Long nodeId, final String event) {
-        return new StringBuilder("OF Switch ").append(nodeId).append(event).toString();
-    }
-
-    /**
-     * Method gets the source text for the nodeId.
-     *
-     * @param nodeId Source of the alarm nodeId
-     */
-    private static String getSourceText(final Long nodeId) {
-        return "Dpn=" + nodeId;
-    }
-}
index 5a7d4b2e78e95c25d057bed2cb68d97c6a74710e..c8f9d4d6f86368720d0f3ab40135f363056e4325 100644 (file)
@@ -5,7 +5,6 @@
  * 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.southboundcli.alarm;
 
 import com.google.common.collect.ImmutableList;
@@ -15,11 +14,11 @@ import java.util.concurrent.atomic.AtomicLong;
 import javax.management.AttributeChangeNotification;
 import javax.management.NotificationBroadcasterSupport;
 
-public class NodeReconciliationAlarm extends NotificationBroadcasterSupport implements NodeReconciliationAlarmMBean {
-
-    private AtomicLong sequenceNumber = new AtomicLong(1);
+public final class NodeReconciliationAlarm extends NotificationBroadcasterSupport
+        implements NodeReconciliationAlarmMBean {
+    private final AtomicLong sequenceNumber = new AtomicLong(1);
 
-    private volatile java.util.List<String> raiseAlarmObject = new ArrayList<>();
+    private volatile List<String> raiseAlarmObject = new ArrayList<>();
     private volatile List<String> clearAlarmObject = new ArrayList<>();
 
     @Override
index 2745a6b5daa9a4f5ef25e0882a5fc88030044df4..d13cf6e7ff739c824b6f7cd5daa6bd83f5c16eb3 100644 (file)
@@ -11,9 +11,6 @@
     <reference id="frm"
                interface="org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager"/>
 
-    <bean id="alarmAgent"
-          class="org.opendaylight.openflowplugin.applications.southboundcli.alarm.AlarmAgent" init-method="start">
-    </bean>
     <bean id="nodeListener"
           class="org.opendaylight.openflowplugin.applications.southboundcli.NodeListener"
           init-method="start"
@@ -25,7 +22,6 @@
           destroy-method="close">
         <argument ref="dataBroker"/>
         <argument ref="frm"/>
-        <argument ref="alarmAgent"/>
         <argument ref="nodeListener"/>
         <argument ref="flowCacheManager"/>
     </bean>