From 65dee45c5bf031067cd4eca208a6b4a8c56eaa84 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 11 Feb 2024 22:18:03 +0100 Subject: [PATCH] Eliminate AlarmAgent 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 --- .../ReconciliationServiceImpl.java | 87 +++++++++-- .../southboundcli/alarm/AlarmAgent.java | 141 ------------------ .../alarm/NodeReconciliationAlarm.java | 9 +- .../OSGI-INF/blueprint/southbound-cli.xml | 4 - 4 files changed, 79 insertions(+), 162 deletions(-) delete mode 100644 applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/AlarmAgent.java diff --git a/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/ReconciliationServiceImpl.java b/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/ReconciliationServiceImpl.java index f09f748fd9..0f8faf0503 100644 --- a/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/ReconciliationServiceImpl.java +++ b/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/ReconciliationServiceImpl.java @@ -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 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 index 5f20a88ce8..0000000000 --- a/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/AlarmAgent.java +++ /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; - } -} diff --git a/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/NodeReconciliationAlarm.java b/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/NodeReconciliationAlarm.java index 5a7d4b2e78..c8f9d4d6f8 100644 --- a/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/NodeReconciliationAlarm.java +++ b/applications/southbound-cli/src/main/java/org/opendaylight/openflowplugin/applications/southboundcli/alarm/NodeReconciliationAlarm.java @@ -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 raiseAlarmObject = new ArrayList<>(); + private volatile List raiseAlarmObject = new ArrayList<>(); private volatile List clearAlarmObject = new ArrayList<>(); @Override diff --git a/applications/southbound-cli/src/main/resources/OSGI-INF/blueprint/southbound-cli.xml b/applications/southbound-cli/src/main/resources/OSGI-INF/blueprint/southbound-cli.xml index 2745a6b5da..d13cf6e7ff 100644 --- a/applications/southbound-cli/src/main/resources/OSGI-INF/blueprint/southbound-cli.xml +++ b/applications/southbound-cli/src/main/resources/OSGI-INF/blueprint/southbound-cli.xml @@ -11,9 +11,6 @@ - - - -- 2.36.6