aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--appc-oam/appc-oam-bundle/pom.xml84
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/AppcOam.java612
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/OAMCommandStatus.java40
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/Converter.java82
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/MessageAdapter.java140
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseActionRunnable.java207
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseCommon.java216
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseProcessor.java166
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamMmodeProcessor.java163
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamRestartProcessor.java207
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamStartProcessor.java151
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamStopProcessor.java120
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/AsyncTaskHelper.java165
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/BundleFilter.java128
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/BundleHelper.java265
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/ConfigurationHelper.java80
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/OperationHelper.java205
-rw-r--r--appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/StateHelper.java144
-rw-r--r--appc-oam/appc-oam-model/src/main/yang/appc-oam.yang69
19 files changed, 2687 insertions, 557 deletions
diff --git a/appc-oam/appc-oam-bundle/pom.xml b/appc-oam/appc-oam-bundle/pom.xml
index 1da4a7eee..20cfbf819 100644
--- a/appc-oam/appc-oam-bundle/pom.xml
+++ b/appc-oam/appc-oam-bundle/pom.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@@ -28,7 +30,7 @@
org.openecomp.appc.adapter.messaging.*,
org.openecomp.appc.adapter.message.*,
org.openecomp.appc.adapter.factory.*,
- org.openecomp.appc.listener.*,
+ org.openecomp.appc.listener,
*;resolution:=optional
</Import-Package>
<Embed-Dependency>
@@ -161,7 +163,21 @@
<artifactId>appc-request-handler-api</artifactId>
<version>${project.version}</version>
</dependency>
-
+ <dependency>
+ <groupId>org.openecomp.appc</groupId>
+ <artifactId>appc-lifecycle-management-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.appc</groupId>
+ <artifactId>appc-lifecycle-management-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.appc</groupId>
+ <artifactId>state-machine-lib</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
@@ -207,6 +223,24 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.10.19</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
<!-- TEMP CODE -->
<dependency>
<groupId>org.json</groupId>
@@ -214,30 +248,30 @@
</dependency>
- <dependency>
- <groupId>org.openecomp.appc</groupId>
- <artifactId>appc-message-adapter-api</artifactId>
- <version>${project.version}</version>
+ <dependency>
+ <groupId>org.openecomp.appc</groupId>
+ <artifactId>appc-message-adapter-api</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.appc</groupId>
+ <artifactId>appc-message-adapter-factory</artifactId>
+ <version>${project.version}</version>
<scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.openecomp.appc</groupId>
- <artifactId>appc-message-adapter-factory</artifactId>
- <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.appc</groupId>
+ <artifactId>appc-dmaap-adapter-bundle</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.appc</groupId>
+ <artifactId>appc-event-listener-bundle</artifactId>
+ <version>${project.version}</version>
<scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.openecomp.appc</groupId>
- <artifactId>appc-dmaap-adapter-bundle</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.openecomp.appc</groupId>
- <artifactId>appc-event-listener-bundle</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
+ </dependency>
</dependencies>
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/AppcOam.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/AppcOam.java
index 8fd6b2c1a..7ad3b6201 100644
--- a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/AppcOam.java
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/AppcOam.java
@@ -24,97 +24,74 @@
package org.openecomp.appc.oam;
-import org.openecomp.appc.Constants;
-import org.openecomp.appc.configuration.Configuration;
-import org.openecomp.appc.configuration.ConfigurationFactory;
-import org.openecomp.appc.exceptions.APPCException;
-import org.openecomp.appc.executor.objects.Params;
-import org.openecomp.appc.i18n.Msg;
-import org.openecomp.appc.logging.LoggingConstants;
-import org.openecomp.appc.logging.LoggingUtils;
-import org.openecomp.appc.metricservice.MetricRegistry;
-import org.openecomp.appc.metricservice.MetricService;
-import org.openecomp.appc.metricservice.metric.Metric;
-import org.openecomp.appc.requesthandler.LCMStateManager;
-import org.openecomp.appc.requesthandler.RequestHandler;
import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
-import com.att.eelf.i18n.EELFResourceManager;
import com.google.common.util.concurrent.Futures;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.*;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.AppcOamService;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.AppcState;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.GetAppcStateOutput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.GetAppcStateOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.GetMetricsOutput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.GetMetricsOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.MaintenanceModeInput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.MaintenanceModeOutput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.MaintenanceModeOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.RestartInput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.RestartOutput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.RestartOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StartInput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StartOutput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StartOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StopInput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StopOutput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StopOutputBuilder;
import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.common.header.CommonHeader;
import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.Metrics;
import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.MetricsBuilder;
import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.metrics.KpiValues;
import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.metrics.KpiValuesBuilder;
import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.Status;
-import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.StatusBuilder;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
-import org.slf4j.MDC;
-
-import java.net.InetAddress;
-import java.util.*;
-import java.util.concurrent.*;
-
-import org.openecomp.appc.oam.messageadapter.*;
-
-
-import static com.att.eelf.configuration.Configuration.*;
-
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.i18n.Msg;
+import org.openecomp.appc.metricservice.MetricRegistry;
+import org.openecomp.appc.metricservice.MetricService;
+import org.openecomp.appc.metricservice.metric.Metric;
+import org.openecomp.appc.oam.processor.OamMmodeProcessor;
+import org.openecomp.appc.oam.processor.OamRestartProcessor;
+import org.openecomp.appc.oam.processor.OamStartProcessor;
+import org.openecomp.appc.oam.processor.OamStopProcessor;
+import org.openecomp.appc.oam.util.AsyncTaskHelper;
+import org.openecomp.appc.oam.util.ConfigurationHelper;
+import org.openecomp.appc.oam.util.OperationHelper;
+import org.openecomp.appc.oam.util.StateHelper;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamMetaDataReader.AppcOperation;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.Executors;
import java.util.concurrent.Future;
-
+/**
+ * RPC class of APP-C OAM API.
+ * <p>Implement all the RPCs defined in AppcOamService through yang model definition.
+ * <p>All RPC methods' JAVADOC are using "inheritDoc" to use the description from the yang model file.
+ */
public class AppcOam implements AutoCloseable, AppcOamService {
-
- private Configuration configuration = ConfigurationFactory.getConfiguration();
- private final EELFLogger logger = EELFManager.getInstance().getLogger(AppcOam.class);
-
- private boolean isMetricEnabled = false;
-
-
- private final ScheduledExecutorService scheduledExecutorService;
-
- private volatile ScheduledFuture<?> outstandingLCMRequestMonitorSheduledFuture;
-
-
- private MessageAdapter messageAdapter;
-
-
/**
- * The ODL data store broker. Provides access to a conceptual data tree store and also provides the ability to
- * subscribe for changes to data under a given branch of the tree.
+ * Invalid state message format with fliexible operation, appc name and state values
*/
- private DataBroker dataBroker;
+ public final static String INVALID_STATE_MESSAGE_FORMAT = "%s API is not allowed when %s is in the %s state.";
- /**
- * ODL Notification Service that provides publish/subscribe capabilities for YANG modeled notifications.
- */
- private NotificationProviderService notificationService;
+ private final EELFLogger logger = EELFManager.getInstance().getLogger(AppcOam.class);
- /**
- * Provides a registry for Remote Procedure Call (RPC) service implementations. The RPCs are defined in YANG models.
- */
- private RpcProviderRegistry rpcRegistry;
+ private boolean isMetricEnabled = false;
/**
* Represents our RPC implementation registration
@@ -123,62 +100,74 @@ public class AppcOam implements AutoCloseable, AppcOamService {
/**
- * The yang rpc names
+ * The yang rpc names with value mapping to AppcOperation
*/
public enum RPC {
- start,
- stop,
- ;
+ maintenance_mode(AppcOperation.MaintenanceMode),
+ start(AppcOperation.Start),
+ stop(AppcOperation.Stop),
+ restart(AppcOperation.Restart);
+
+ AppcOperation appcOperation;
+
+ RPC(AppcOperation appcOperation) {
+ this.appcOperation = appcOperation;
+ }
+
+ public AppcOperation getAppcOperation() {
+ return appcOperation;
+ }
}
+ private AsyncTaskHelper asyncTaskHelper;
+ private ConfigurationHelper configurationHelper;
+ private OperationHelper operationHelper;
+ private StateHelper stateHelper;
/**
- * @param dataBroker
- * @param notificationProviderService
- * @param rpcProviderRegistry
+ * APP-C OAM contructor
+ *
+ * @param dataBroker object of The ODL data store broker. Provides access to a conceptual data
+ * tree store
+ * and also provides the ability to subscribe for changes to data under a
+ * given branch
+ * of the tree. Not used in this class.
+ * @param notificationProviderService object of ODL Notification Service that provides publish/subscribe
+ * capabilities for YANG modeled notifications. Not used in this class.
+ * @param rpcProviderRegistry object of RpcProviderResigstry. Used to register our RPCs.
*/
- @SuppressWarnings({
- "javadoc", "nls"
- })
- public AppcOam(DataBroker dataBroker, NotificationProviderService notificationProviderService,
+ @SuppressWarnings({"unused", "nls"})
+ public AppcOam(DataBroker dataBroker,
+ NotificationProviderService notificationProviderService,
RpcProviderRegistry rpcProviderRegistry) {
- String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
+ configurationHelper = new ConfigurationHelper(logger);
+ String appName = configurationHelper.getAppcName();
logger.info(Msg.COMPONENT_INITIALIZING, appName, "oam");
- this.dataBroker = dataBroker;
- this.notificationService = notificationProviderService;
- this.rpcRegistry = rpcProviderRegistry;
-
- if (this.rpcRegistry != null) {
- rpcRegistration = rpcRegistry.addRpcImplementation(AppcOamService.class, this);
+ if (rpcProviderRegistry != null) {
+ rpcRegistration = rpcProviderRegistry.addRpcImplementation(AppcOamService.class, this);
}
- Properties properties = configuration.getProperties();
- if (properties != null && properties.getProperty("metric.enabled") != null) {
- isMetricEnabled = Boolean.valueOf(properties.getProperty("metric.enabled"));
- }
-
-
- messageAdapter = new MessageAdapter();
- messageAdapter.init();
+ isMetricEnabled = configurationHelper.isMetricEnabled();
-
- scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(
- new ThreadFactory(){
-
- @Override
- public Thread newThread(Runnable runnable) {
- Bundle bundle = FrameworkUtil.getBundle(AppcOam.class);
- return new Thread(runnable,bundle.getSymbolicName() + " scheduledExecutor");
- }
- }
- );
+ initHelpers();
logger.info(Msg.COMPONENT_INITIALIZED, appName, "oam");
}
/**
+ * Initialize helper classes.
+ * <p>Note: ConfigurationHelper initializetion is in included here
+ * because it is needed for extracting the AppName used in the debug logs within the constructor.
+ */
+ private void initHelpers() {
+ operationHelper = new OperationHelper();
+ asyncTaskHelper = new AsyncTaskHelper(logger);
+ stateHelper = new StateHelper(logger, configurationHelper);
+ }
+
+ /**
* Implements the close of the service
*
* @see AutoCloseable#close()
@@ -186,58 +175,65 @@ public class AppcOam implements AutoCloseable, AppcOamService {
@SuppressWarnings("nls")
@Override
public void close() throws Exception {
- String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
+ String appName = configurationHelper.getAppcName();
logger.info(Msg.COMPONENT_TERMINATING, appName, "oam");
- scheduledExecutorService.shutdown();
+
+ asyncTaskHelper.close();
+
if (rpcRegistration != null) {
rpcRegistration.close();
}
logger.info(Msg.COMPONENT_TERMINATED, appName, "oam");
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public Future<RpcResult<GetMetricsOutput>> getMetrics() {
- GetMetricsOutputBuilder outputBuilder = new GetMetricsOutputBuilder();
-
- if (!isMetricEnabled){
+ if (!isMetricEnabled) {
logger.error("Metric Service not enabled returning failure");
- RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(false).withError(RpcError.ErrorType.APPLICATION,"Metric Service not enabled").build();
+ RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput>
+ status(false).withError(RpcError.ErrorType.APPLICATION, "Metric Service not enabled").build();
return Futures.immediateFuture(result);
}
- MetricService metricService = null;
+ MetricService metricService;
try {
- metricService = getService(MetricService.class);
- } catch (APPCException e){
- logger.error("MetricService not found",e);
- RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(false).withError(RpcError.ErrorType.APPLICATION,"Metric Service not found").build();
+ metricService = operationHelper.getService(MetricService.class);
+ } catch (APPCException e) {
+ logger.error("MetricService not found", e);
+ RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput>
+ status(false).withError(RpcError.ErrorType.APPLICATION, "Metric Service not found").build();
return Futures.immediateFuture(result);
}
- Map<String,MetricRegistry> allMetricRegitry = metricService.getAllRegistry();
- if(allMetricRegitry == null || allMetricRegitry.isEmpty()){
+ Map<String, MetricRegistry> allMetricRegitry = metricService.getAllRegistry();
+ if (allMetricRegitry == null || allMetricRegitry.isEmpty()) {
logger.error("No metrics registered returning failure");
- RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(false).withError(RpcError.ErrorType.APPLICATION,"No metrics Registered").build();
+ RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput>
+ status(false).withError(RpcError.ErrorType.APPLICATION, "No metrics Registered").build();
return Futures.immediateFuture(result);
}
+
List<Metrics> metricsList = new ArrayList<>();
logger.debug("Iterating metric registry list");
- for (MetricRegistry metricRegistry : allMetricRegitry.values() ) {
+ for (MetricRegistry metricRegistry : allMetricRegitry.values()) {
logger.debug("Iterating metric registry :" + metricRegistry.toString());
- Metric[] metrics = metricRegistry.metrics() ;
- if(metrics!= null && metrics.length >0) {
+ Metric[] metrics = metricRegistry.metrics();
+ if (metrics != null && metrics.length > 0) {
logger.debug("Iterating though metrics in registry");
for (Metric metric : metrics) {
- logger.debug("Iterating though metrics: "+ metric.name());
+ logger.debug("Iterating though metrics: " + metric.name());
MetricsBuilder metricsBuilder = new MetricsBuilder();
metricsBuilder.setKpiName(metric.name());
metricsBuilder.setLastResetTime(metric.getLastModified());
List<KpiValues> kpiList = new ArrayList<>();
Map<String, String> metricsOutput = metric.getMetricsOutput();
for (Map.Entry<String, String> kpi : metricsOutput.entrySet()) {
- KpiValuesBuilder kpiValuesBuilder = new KpiValuesBuilder();
+ KpiValuesBuilder kpiValuesBuilder = new KpiValuesBuilder();
kpiValuesBuilder.setName(kpi.getKey());
kpiValuesBuilder.setValue(kpi.getValue());
kpiList.add(kpiValuesBuilder.build());
@@ -247,339 +243,97 @@ public class AppcOam implements AutoCloseable, AppcOamService {
}
}
}
+
+ GetMetricsOutputBuilder outputBuilder = new GetMetricsOutputBuilder();
outputBuilder.setMetrics(metricsList);
- RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(true).withResult(outputBuilder.build()).build();
+ RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput>
+ status(true).withResult(outputBuilder.build()).build();
return Futures.immediateFuture(result);
}
+ /**
+ * {@inheritDoc}
+ */
@Override
- public Future<RpcResult<StopOutput>> stop(StopInput stopInput){
- logger.debug("Input received : " + stopInput);
- final Date startTime = new Date();
- Status status = this.buildStatus(OAMCommandStatus.ACCEPTED);
- final CommonHeader commonHeader = stopInput.getCommonHeader();
+ public Future<RpcResult<StopOutput>> stop(StopInput stopInput) {
+ logger.debug("Entering Stop with Input : " + stopInput);
+ final CommonHeader commonHeader = stopInput.getCommonHeader();
- try {
- setInitialLogProperties(commonHeader,RPC.stop);
-
- //Close the gate so that no more new LCM request will be excepted.
- LCMStateManager lcmStateManager = getService(LCMStateManager.class);
- lcmStateManager.disableLCMOperations();
- //Begin monitoring outstanding LCM request
- scheduleOutstandingLCMRequestMonitor(commonHeader,startTime);
- } catch(Throwable t) {
- status = unexpectedOAMError(t,RPC.stop);
- }
- finally {
- LoggingUtils.auditWarn(startTime.toInstant(),
- new Date(System.currentTimeMillis()).toInstant(),
- String.valueOf(status.getCode()),
- status.getMessage(),
- this.getClass().getCanonicalName(),
- Msg.OAM_OPERATION_STOPPING,
- getAppcName()
- );
- this.clearRequestLogProperties();
- }
+ OamStopProcessor oamStopProcessor =
+ new OamStopProcessor(logger, configurationHelper, stateHelper, asyncTaskHelper, operationHelper);
+ Status status = oamStopProcessor.processRequest(stopInput);
StopOutputBuilder stopOutputBuilder = new StopOutputBuilder();
stopOutputBuilder.setStatus(status);
stopOutputBuilder.setCommonHeader(commonHeader);
- StopOutput stopOutput = stopOutputBuilder.build();
- return RpcResultBuilder.success(stopOutput).buildFuture();
+ return RpcResultBuilder.success(stopOutputBuilder.build()).buildFuture();
}
+ /**
+ * {@inheritDoc}
+ */
@Override
- public Future<RpcResult<StartOutput>> start(StartInput startInput){
- logger.debug("Input received : " + startInput);
- final Date startTime = new Date();
- Status status = this.buildStatus(OAMCommandStatus.ACCEPTED);
- final CommonHeader commonHeader = startInput.getCommonHeader();
-
- try {
-
-
- setInitialLogProperties(commonHeader,RPC.start);
-
- this.scheduleStartingAPPC(commonHeader,startTime);
- } catch(Throwable t) {
- status = unexpectedOAMError(t,RPC.start);
- }
- finally {
- LoggingUtils.auditWarn(startTime.toInstant(),
- new Date(System.currentTimeMillis()).toInstant(),
- String.valueOf(status.getCode()),
- status.getMessage(),
- this.getClass().getCanonicalName(),
- Msg.OAM_OPERATION_STARTING,
- getAppcName()
- );
- this.clearRequestLogProperties();
- }
-
- StartOutputBuilder startOutputBuilder = new StartOutputBuilder();
- startOutputBuilder.setStatus(status);
- startOutputBuilder.setCommonHeader(commonHeader);
- StartOutput startOutput = startOutputBuilder.build();
- return RpcResultBuilder.success(startOutput).buildFuture();
- }
+ public Future<RpcResult<RestartOutput>> restart(RestartInput input) {
+ logger.debug("Entering restart with Input : " + input);
+ final CommonHeader commonHeader = input.getCommonHeader();
- private <T> T getService(Class<T> _class) throws APPCException {
- BundleContext bctx = FrameworkUtil.getBundle(_class).getBundleContext();
- ServiceReference sref = bctx.getServiceReference(_class.getName());
- if (sref != null) {
- if(logger.isTraceEnabled()) {
- logger.debug("Using the BundleContext to fetched the service reference for " + _class.getName());
+ OamRestartProcessor oamRestartProcessor =
+ new OamRestartProcessor(logger, configurationHelper, stateHelper, asyncTaskHelper, operationHelper);
+ Status status = oamRestartProcessor.processRequest(input);
- }
- return (T) bctx.getService(sref);
- } else {
- throw new APPCException("Using the BundleContext failed to to fetch service reference for " + _class.getName());
- }
- }
-
- private Status buildStatus(OAMCommandStatus osmCommandStatus){
- StatusBuilder status = new StatusBuilder();
- status.setCode(osmCommandStatus.getResponseCode());
- status.setMessage(osmCommandStatus.getResponseMessage());
- return status.build();
- }
+ RestartOutputBuilder restartOutputBuilder = new RestartOutputBuilder();
+ restartOutputBuilder.setStatus(status);
+ restartOutputBuilder.setCommonHeader(commonHeader);
- private Status buildStatus(OAMCommandStatus osmCommandStatus,Params params){
- StatusBuilder status = new StatusBuilder();
- status.setCode(osmCommandStatus.getResponseCode());
- status.setMessage(osmCommandStatus.getFormattedMessage(params));
- return status.build();
+ return RpcResultBuilder.success(restartOutputBuilder.build()).buildFuture();
}
-
-
- private void clearRequestLogProperties() {
- try {
- MDC.remove(MDC_KEY_REQUEST_ID);
- MDC.remove(MDC_SERVICE_INSTANCE_ID);
- MDC.remove(MDC_SERVICE_NAME);
- MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
- MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
- } catch (Exception e) {
-
- }
- }
-
- private void setInitialLogProperties(CommonHeader commonHeader,RPC action) {
-
- try {
- MDC.put(MDC_KEY_REQUEST_ID, commonHeader.getRequestId());
- MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, commonHeader.getOriginatorId());
- MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
- try {
- MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
- MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
- MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
- MDC.put(MDC_SERVICE_NAME, action.name());
- } catch (Exception e) {
- logger.debug("MDC constant error",e);
- }
- } catch (RuntimeException e) {
- //ignore
- }
- }
-
-
- private void storeErrorMessageToLog(Status status, String additionalMessage) {
- LoggingUtils.logErrorMessage(
- String.valueOf(status.getCode()),
- status.getMessage(),
- LoggingConstants.TargetNames.APPC,
- LoggingConstants.TargetNames.APPC_OAM_PROVIDER,
- additionalMessage,
- this.getClass().getCanonicalName());
- }
-
- private String getAppcName(){
- return configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
- }
-
- private Status unexpectedOAMError(Throwable t,RPC action){
- final String appName = getAppcName();
-
- String exceptionMessage = t.getMessage() != null ? t.getMessage() : t.toString();
-
- String errorMessage = EELFResourceManager.format(Msg.OAM_OPERATION_EXCEPTION, t, appName, t.getClass().getSimpleName(), action.name(), exceptionMessage);
-
- Params params = new Params().addParam("errorMsg", exceptionMessage);
- Status status = buildStatus(
- OAMCommandStatus.UNEXPECTED_ERROR,
- params
- );
-
- storeErrorMessageToLog(status,errorMessage);
- return status;
- }
-
-
- private int getInprogressLCMRequestCount() throws APPCException {
- RequestHandler requestHandler = getService(RequestHandler.class);
-
- if(requestHandler == null) {
- return 0;
- }
-
- int inprogressRequestCount = requestHandler.getInprogressRequestCount();
- return inprogressRequestCount;
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Future<RpcResult<MaintenanceModeOutput>> maintenanceMode(MaintenanceModeInput maintenanceModeInput) {
+ logger.debug("Entering MaintenanceMode with Input : " + maintenanceModeInput);
+ final CommonHeader commonHeader = maintenanceModeInput.getCommonHeader();
+
+ OamMmodeProcessor oamMmodeProcessor =
+ new OamMmodeProcessor(logger, configurationHelper, stateHelper, asyncTaskHelper, operationHelper);
+ Status status = oamMmodeProcessor.processRequest(maintenanceModeInput);
+
+ MaintenanceModeOutputBuilder maintenanceModeOutputBuilder = new MaintenanceModeOutputBuilder();
+ maintenanceModeOutputBuilder.setStatus(status);
+ maintenanceModeOutputBuilder.setCommonHeader(commonHeader);
+ return RpcResultBuilder.success(maintenanceModeOutputBuilder.build()).buildFuture();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Future<RpcResult<GetAppcStateOutput>> getAppcState() {
+ AppcState appcState = stateHelper.getCurrentOamYangState();
-
- private void scheduleOutstandingLCMRequestMonitor(final CommonHeader commonHeader,final Date startTime){
-
-
- class MyCommand implements Runnable{
-
- public ScheduledFuture<?> myScheduledFuture = null;
-
- @Override
- public void run() {
- try {
- setInitialLogProperties(commonHeader, RPC.stop);
-
-
- logDebug("Executing stopping task ");
-
- ScheduledFuture<?> currentScheduledFuture = AppcOam.this.outstandingLCMRequestMonitorSheduledFuture;
-
- //cancel myself if I am not the current outstandingLCMRequestMonitor
- if(currentScheduledFuture != myScheduledFuture){
- myScheduledFuture.cancel(false);
- return;
- }
-
- Status status = buildStatus(OAMCommandStatus.SUCCESS);
-
-
- try {
-
- //log status and return if there are still LCM request in progress
- int inprogressRequestCount = getInprogressLCMRequestCount();
- if (inprogressRequestCount > 0) {
- logDebug("The application '%s' has '%s' outstanding LCM request to complete before coming to a complete stop. ",
- getAppcName(),
- inprogressRequestCount
- );
- return;
- }
-
- } catch (Throwable t) {
- status = unexpectedOAMError(t, RPC.stop);
- myScheduledFuture.cancel(false);
- }
-
- try {
- OAMContext oamContext = new OAMContext();
- oamContext.setRpcName(RPC.stop);
- oamContext.setCommonHeader(commonHeader);
- oamContext.setStatus(status);
- messageAdapter.post(oamContext);
- } catch(Throwable t) {
- status = unexpectedOAMError(t,RPC.stop);
- }
-
- LoggingUtils.auditWarn(startTime.toInstant(),
- new Date(System.currentTimeMillis()).toInstant(),
- String.valueOf(status.getCode()),
- status.getMessage(),
- this.getClass().getCanonicalName(),
- Msg.OAM_OPERATION_STOPPED,
- getAppcName()
- );
- myScheduledFuture.cancel(false);
-
- } finally {
- clearRequestLogProperties();
- }
- }
- };
-
- MyCommand command = new MyCommand();
-
- long initialDelay = 10000;
- long delay = initialDelay;
-
-
- command.myScheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(
- command,
- initialDelay,
- delay,
- TimeUnit.MILLISECONDS
- );
- this.outstandingLCMRequestMonitorSheduledFuture = command.myScheduledFuture;
+ GetAppcStateOutputBuilder builder = new GetAppcStateOutputBuilder();
+ builder.setState(appcState);
+ return RpcResultBuilder.success(builder.build()).buildFuture();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Future<RpcResult<StartOutput>> start(StartInput startInput) {
+ logger.debug("Input received : " + startInput);
+ final CommonHeader commonHeader = startInput.getCommonHeader();
+ OamStartProcessor oamStartProcessor =
+ new OamStartProcessor(logger, configurationHelper, stateHelper, asyncTaskHelper, operationHelper);
+ Status status = oamStartProcessor.processRequest(startInput);
-
- private void scheduleStartingAPPC(final CommonHeader commonHeader,final Date startTime){
-
-
- class MyCommand implements Runnable{
-
-
- @Override
- public void run() {
- try {
- setInitialLogProperties(commonHeader, RPC.start);
-
- logDebug("Executing starting task ");
-
- Status status = buildStatus(OAMCommandStatus.SUCCESS);
-
- try {
- LCMStateManager lcmStateManager = getService(LCMStateManager.class);
- lcmStateManager.enableLCMOperations();
- //cancel the current outstandingLCMRequestMonitor
- outstandingLCMRequestMonitorSheduledFuture = null;
- } catch(Throwable t) {
- status = unexpectedOAMError(t,RPC.start);
- }
-
- try {
- OAMContext oamContext = new OAMContext();
- oamContext.setRpcName(RPC.start);
- oamContext.setCommonHeader(commonHeader);
- oamContext.setStatus(status);
- messageAdapter.post(oamContext);
- } catch(Throwable t) {
- status = unexpectedOAMError(t,RPC.start);
- }
-
- LoggingUtils.auditWarn(startTime.toInstant(),
- new Date(System.currentTimeMillis()).toInstant(),
- String.valueOf(status.getCode()),
- status.getMessage(),
- this.getClass().getCanonicalName(),
- Msg.OAM_OPERATION_STARTED,
- getAppcName()
- );
- } finally {
- clearRequestLogProperties();
- }
- }
- };
-
- MyCommand command = new MyCommand();
- long initialDelay = 1000;
-
- scheduledExecutorService.schedule(
- command,
- initialDelay,
- TimeUnit.MILLISECONDS
- );
- }
-
-
- private void logDebug(String message,Object... args){
- if (logger.isDebugEnabled()) {
- logger.debug(String.format(message,args));
- }
+ StartOutputBuilder startOutputBuilder = new StartOutputBuilder();
+ startOutputBuilder.setStatus(status);
+ startOutputBuilder.setCommonHeader(commonHeader);
+ StartOutput startOutput = startOutputBuilder.build();
+ return RpcResultBuilder.success(startOutput).buildFuture();
}
}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/OAMCommandStatus.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/OAMCommandStatus.java
index cef242cf5..378fa032d 100644
--- a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/OAMCommandStatus.java
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/OAMCommandStatus.java
@@ -34,17 +34,18 @@ public enum OAMCommandStatus {
ACCEPTED(100,"ACCEPTED - request accepted"),
- //ERROR(2xx) – request can’t be handled due to some technical error
+ //ERROR(2xx) - request can't be handled due to some technical error
UNEXPECTED_ERROR(200,"UNEXPECTED ERROR - ${errorMsg}"),
- SUCCESS(400,"SUCCESS - request has been processed successfully"),
- ;
-
+ REJECTED(300,"REJECTED - ${errorMsg}"),
+ INVALID_PARAMETER(302,"INVALID PARAMETER - ${errorMsg}" ),
+ TIMEOUT(303, "OPERATION TIMEOUT REACHED - ${errorMsg}"),
- public static final String errorDgMessageParamName = "errorDgMessage";
+ SUCCESS(400,"SUCCESS - request has been processed successfully"),
+ ;
- private int responseCode;
- private String responseMessage;
+ private int responseCode;
+ private String responseMessage;
@@ -52,31 +53,25 @@ public enum OAMCommandStatus {
OAMCommandStatus(int responseCode, String responseMessage) {
this.responseCode = responseCode;
this.responseMessage = responseMessage;
- }
+ }
public String getResponseMessage() {
- return responseMessage;
- }
+ return responseMessage;
+ }
- public int getResponseCode() {
- return responseCode;
- }
+ public int getResponseCode() {
+ return responseCode;
+ }
- /**
+ /**
*
* @return messageTemplate
*/
-
-
public String getFormattedMessage(Params params){
- Map<String,Object> paramsMap = params != null ? params.getParams() : null;
- return MessageFormatter.format(getResponseMessage(),paramsMap);
+ Map<String,Object> paramsMap = params != null ? params.getParams() : null;
+ return MessageFormatter.format(getResponseMessage(),paramsMap);
- }
-
- public String getFormattedMessageWithCode(Params params){
- return getResponseCode()+"-" + getFormattedMessage(params);
}
@Override
@@ -87,4 +82,3 @@ public enum OAMCommandStatus {
'}';
}
}
-
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/Converter.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/Converter.java
index e9ccfdd2d..a70d12042 100644
--- a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/Converter.java
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/Converter.java
@@ -1,4 +1,4 @@
-/*-
+/*-/*-
* ============LICENSE_START=======================================================
* ONAP : APPC
* ================================================================================
@@ -24,9 +24,6 @@
package org.openecomp.appc.oam.messageadapter;
-import org.openecomp.appc.oam.AppcOam;
-import com.att.eelf.configuration.EELFLogger;
-import com.att.eelf.configuration.EELFManager;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -35,12 +32,15 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
-import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.*;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.MaintenanceModeOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.RestartOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StartOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StopOutputBuilder;
import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.common.header.CommonHeader;
import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.Status;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.binding.DataContainer;
-
+import org.openecomp.appc.oam.AppcOam;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
@@ -48,61 +48,81 @@ import java.util.TimeZone;
public class Converter {
private static final String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private static final SimpleDateFormat isoFormatter = new SimpleDateFormat(ISO_FORMAT);
- private static final EELFLogger logger = EELFManager.getInstance().getLogger(Converter.class);
+
static {
isoFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
- private static Builder<?> convAsyncResponseToBuilder1(AppcOam.RPC rpcName, CommonHeader commonHeader, Status status) {
- Builder<?> outObj = null;
- if(rpcName == null){
+ private static Builder<?> convAsyncResponseToBuilder1(AppcOam.RPC rpcName,
+ CommonHeader commonHeader,
+ Status status) {
+ Builder<?> outObj;
+ if (rpcName == null) {
throw new IllegalArgumentException("empty asyncResponse.rpcName");
}
- if(commonHeader == null){
+ if (commonHeader == null) {
throw new IllegalArgumentException("empty asyncResponse.commonHeader");
}
- if(status == null){
+ if (status == null) {
throw new IllegalArgumentException("empty asyncResponse.status");
}
- switch (rpcName){
- case stop:
- outObj = new StopOutputBuilder();
- ((StopOutputBuilder)outObj).setCommonHeader(commonHeader);
- ((StopOutputBuilder)outObj).setStatus(status);
+ switch (rpcName) {
+ case maintenance_mode:
+ outObj = new MaintenanceModeOutputBuilder();
+ ((MaintenanceModeOutputBuilder) outObj).setCommonHeader(commonHeader);
+ ((MaintenanceModeOutputBuilder) outObj).setStatus(status);
return outObj;
case start:
outObj = new StartOutputBuilder();
- ((StartOutputBuilder)outObj).setCommonHeader(commonHeader);
- ((StartOutputBuilder)outObj).setStatus(status);
+ ((StartOutputBuilder) outObj).setCommonHeader(commonHeader);
+ ((StartOutputBuilder) outObj).setStatus(status);
+ return outObj;
+
+ case stop:
+ outObj = new StopOutputBuilder();
+ ((StopOutputBuilder) outObj).setCommonHeader(commonHeader);
+ ((StopOutputBuilder) outObj).setStatus(status);
+ return outObj;
+
+ case restart:
+ outObj = new RestartOutputBuilder();
+ ((RestartOutputBuilder) outObj).setCommonHeader(commonHeader);
+ ((RestartOutputBuilder) outObj).setStatus(status);
return outObj;
+
default:
- throw new IllegalArgumentException(rpcName+" action is not supported");
+ throw new IllegalArgumentException(rpcName + " action is not supported");
}
}
- public static String convAsyncResponseToUebOutgoingMessageJsonString(OAMContext oamContext) throws JsonProcessingException {
+ static String convAsyncResponseToUebOutgoingMessageJsonString(OAMContext oamContext) throws
+ JsonProcessingException {
AppcOam.RPC rpcName = oamContext.getRpcName();
CommonHeader commonHeader = oamContext.getCommonHeader();
Status status = oamContext.getStatus();
- DmaapOutgoingMessage dmaapOutgoingMessage = convAsyncResponseToUebOutgoingMessage(rpcName,commonHeader,status);
+ DmaapOutgoingMessage dmaapOutgoingMessage = convAsyncResponseToUebOutgoingMessage(rpcName, commonHeader,
+ status);
ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.addMixInAnnotations(dmaapOutgoingMessage.getBody().getOutput().getClass(), MixInFlagsMessage.class);
+ objectMapper.addMixInAnnotations(dmaapOutgoingMessage.getBody().getOutput().getClass(),
+ MixInFlagsMessage.class);
objectMapper.addMixInAnnotations(Status.class, MixIn.class);
objectMapper.addMixInAnnotations(CommonHeader.class, MixInCommonHeader.class);
- ObjectWriter writer = objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL).configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true).writer();
+ ObjectWriter writer = objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL).configure
+ (MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true).writer();
return writer.writeValueAsString(dmaapOutgoingMessage);
}
- private static DmaapOutgoingMessage convAsyncResponseToUebOutgoingMessage(AppcOam.RPC rpcName, CommonHeader commonHeader, Status status) throws JsonProcessingException {
+ private static DmaapOutgoingMessage convAsyncResponseToUebOutgoingMessage(AppcOam.RPC rpcName, CommonHeader
+ commonHeader, Status status) throws JsonProcessingException {
DmaapOutgoingMessage outObj = new DmaapOutgoingMessage();
String correlationID = commonHeader.getRequestId();
outObj.setCorrelationID(correlationID);
outObj.setType("response");
outObj.setRpcName(rpcName.name());
- Builder<?> builder = Converter.convAsyncResponseToBuilder1(rpcName,commonHeader,status);
+ Builder<?> builder = Converter.convAsyncResponseToBuilder1(rpcName, commonHeader, status);
Object messageBody = builder.build();
DmaapOutgoingMessage.Body body = new DmaapOutgoingMessage.Body(messageBody);
@@ -112,12 +132,14 @@ public class Converter {
abstract class MixIn {
+ // to be removed during serialization
@JsonIgnore
- abstract Class<? extends DataContainer> getImplementedInterface(); // to be removed during serialization
+ abstract Class<? extends DataContainer> getImplementedInterface();
@JsonValue
abstract java.lang.String getValue();
}
+
abstract class MixInCommonHeader extends MixIn {
@JsonProperty("request-id")
abstract java.lang.String getRequestId();
@@ -126,11 +148,9 @@ public class Converter {
abstract java.lang.String getOriginatorId();
}
+
abstract class MixInFlagsMessage extends MixIn {
@JsonProperty("common-header")
- abstract CommonHeader getCommonHeader();
+ abstract CommonHeader getCommonHeader();
}
-
-
-
}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/MessageAdapter.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/MessageAdapter.java
index 21f096678..d93feabe4 100644
--- a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/MessageAdapter.java
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/messageadapter/MessageAdapter.java
@@ -32,7 +32,6 @@ import org.openecomp.appc.adapter.message.MessageAdapterFactory;
import org.openecomp.appc.adapter.message.Producer;
import org.openecomp.appc.configuration.Configuration;
import org.openecomp.appc.configuration.ConfigurationFactory;
-import org.openecomp.appc.listener.impl.EventHandlerImpl;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
@@ -42,56 +41,84 @@ import java.util.Properties;
public class MessageAdapter {
+ private final EELFLogger logger = EELFManager.getInstance().getLogger(MessageAdapter.class);
+
+ private final String PROP_APPC_OAM_DISABLED = "appc.OAM.disabled";
+ private final String PROP_APPC_OAM_TOPIC_WRITE = "appc.OAM.topic.write";
+ private String PROP_APPC_OAM_CLIENT_KEY = "appc.OAM.client.key";
+ private String PROP_APPC_OAM_CLIENT_SECRET = "appc.OAM.client.secret";
+ private String PROP_APPC_OAM_POOLMEMBERS = "appc.OAM.poolMembers";
+
private Producer producer;
- private String partition ;
+ private String partition;
private Configuration configuration;
private HashSet<String> pool;
private String writeTopic;
private String apiKey;
private String apiSecret;
-
- private static final EELFLogger logger = EELFManager.getInstance().getLogger(MessageAdapter.class);
+ private boolean isDisabled;
/**
- * Initialize producer client to post messages using configuration properties
+ * Initialize producer client to post messages using configuration properties.
*/
- public void init(){
- this.producer = getProducer();
- }
-
- private Producer getProducer() {
+ public void init() {
configuration = ConfigurationFactory.getConfiguration();
- Properties properties=configuration.getProperties();
+ Properties properties = configuration.getProperties();
updateProperties(properties);
- Producer localProducer = null;
-
+
+ if (isAppcOamPropsListenerEnabled()) {
+ createProducer();
+ } else {
+ logger.warn(String.format("The listener %s is disabled and will not be run", "appc.OAM"));
+ }
+ }
+
+ /**
+ * Create producer using MessageAdapterFactory which is found through bundle context.
+ */
+ void createProducer() {
BundleContext ctx = FrameworkUtil.getBundle(MessageAdapter.class).getBundleContext();
- if (ctx != null) {
- ServiceReference svcRef = ctx.getServiceReference(MessageAdapterFactory.class.getName());
- if (svcRef != null) {
- localProducer = ((MessageAdapterFactory) ctx.getService(svcRef)).createProducer(pool, writeTopic, apiKey, apiSecret);
- for (String url : pool) {
- if (url.contains("3905") || url.contains("https")) {
- localProducer.useHttps(true);
- break;
- }
- }
- }
+ if (ctx == null) {
+ logger.warn("MessageAdapter cannot create producer due to no bundle context.");
+ return;
}
- return localProducer;
+ ServiceReference svcRef = ctx.getServiceReference(MessageAdapterFactory.class.getName());
+ if (svcRef == null) {
+ logger.warn("MessageAdapter cannot create producer due to no MessageAdapterFactory service reference.");
+ return;
+ }
+
+ Producer localProducer = ((MessageAdapterFactory) ctx.getService(svcRef)).createProducer(pool, writeTopic,
+ apiKey, apiSecret);
+
+ for (String url : pool) {
+ if (url.contains("3905") || url.contains("https")) {
+ localProducer.useHttps(true);
+ break;
+ }
+ }
+
+ producer = localProducer;
+
+ logger.debug("MessageAdapter created producer.");
}
+ /**
+ * Read property value to set writeTopic, apiKey, apiSecret and pool.
+ *
+ * @param props of configuration
+ */
private void updateProperties(Properties props) {
- if (logger.isTraceEnabled()) {
- logger.trace("Entering to updateProperties with Properties = "+ ObjectUtils.toString(props));
- }
+ logger.trace("Entering to updateProperties with Properties = " + ObjectUtils.toString(props));
+
pool = new HashSet<>();
if (props != null) {
- writeTopic = props.getProperty("appc.OAM.topic.write");
- apiKey = props.getProperty("appc.OAM.client.key");
- apiSecret = props.getProperty("appc.OAM.client.secret");
- String hostnames = props.getProperty("appc.OAM.poolMembers");
+ isDisabled = Boolean.parseBoolean(props.getProperty(PROP_APPC_OAM_DISABLED));
+ writeTopic = props.getProperty(PROP_APPC_OAM_TOPIC_WRITE);
+ apiKey = props.getProperty(PROP_APPC_OAM_CLIENT_KEY);
+ apiSecret = props.getProperty(PROP_APPC_OAM_CLIENT_SECRET);
+ String hostnames = props.getProperty(PROP_APPC_OAM_POOLMEMBERS);
if (hostnames != null && !hostnames.isEmpty()) {
for (String name : hostnames.split(",")) {
pool.add(name);
@@ -101,33 +128,56 @@ public class MessageAdapter {
}
/**
- * Posts message to UEB. As UEB accepts only json messages this method first convert uebMessage to json format and post it to UEB.
- * @param oamContext response data that based on it a message will be send to UEB (the format of the message that will be sent to UEB based on the action and its YANG domainmodel).
- * @return True if message is postes successfully else False
+ * Get producer. If it is null, call createProducer to create it again.
+ *
+ * @return Producer
*/
- public boolean post(OAMContext oamContext){
- boolean success;
+ Producer getProducer() {
+ if (producer == null) {
+ // In case, producer was not properly set yet, set it again.
+ logger.info("Calling createProducer as producer is null.");
+ createProducer();
+ }
+
+ return producer;
+ }
+
+ /**
+ * Posts message to UEB. As UEB accepts only json messages this method first convert uebMessage to json format
+ * and post it to UEB.
+ *
+ * @param oamContext response data that based on it a message will be send to UEB (the format of the message that
+ * will be sent to UEB based on the action and its YANG domainmodel).
+ */
+ public void post(OAMContext oamContext) {
if (logger.isTraceEnabled()) {
logger.trace("Entering to post with AsyncResponse = " + ObjectUtils.toString(oamContext));
}
+ boolean success;
String jsonMessage;
try {
jsonMessage = Converter.convAsyncResponseToUebOutgoingMessageJsonString(oamContext);
if (logger.isDebugEnabled()) {
logger.debug("UEB Response = " + jsonMessage);
}
- success = producer.post(this.partition, jsonMessage);
+
+ Producer myProducer = getProducer();
+ success = myProducer != null && myProducer.post(this.partition, jsonMessage);
} catch (JsonProcessingException e1) {
- logger.error("Error generating Jason from UEB message "+ e1.getMessage());
- success= false;
- }catch (Exception e){
- logger.error("Error sending message to UEB "+e.getMessage());
- success= false;
+ logger.error("Error generating Json from UEB message " + e1.getMessage());
+ success = false;
+ } catch (Exception e) {
+ logger.error("Error sending message to UEB " + e.getMessage(), e);
+ success = false;
}
+
if (logger.isTraceEnabled()) {
- logger.trace("Exiting from post with (success = "+ ObjectUtils.toString(success)+")");
+ logger.trace("Exiting from post with (success = " + ObjectUtils.toString(success) + ")");
}
- return success;
+ }
+
+ private boolean isAppcOamPropsListenerEnabled() {
+ return !isDisabled;
}
}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseActionRunnable.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseActionRunnable.java
new file mode 100644
index 000000000..5df2c805e
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseActionRunnable.java
@@ -0,0 +1,207 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.processor;
+
+import org.openecomp.appc.i18n.Msg;
+import org.openecomp.appc.oam.OAMCommandStatus;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Future;
+
+/**
+ * Base runnable actions for OAM APIs, such as maintenance mode, restart, start and stop API.
+ *
+ * <p>This class holds the general action async handling methods for all OAM APIs.
+ * <p>Specific API action runnable will overwrite the general methods to add specific behaviors.
+ *
+ * <p>Subclass constructor must set the following class variables:
+ * <br> - actionName
+ * <br> - auditMsg
+ * <br> - finalState
+ */
+abstract class BaseActionRunnable extends BaseCommon implements Runnable {
+ final String OAM_OPERATION_TIMEOUT_SECOND = "appc.OAM.api.timeout";
+ /** Default operation tiemout set to 1 minute */
+ final int DEFAULT_OAM_OPERATION_TIMEOUT = 60;
+ /** Abort message format with flexible operation name */
+ final String ABORT_MESSAGE_FORMAT = "Aborting %s operation.";
+ /** Timeout message format with flexible operation name */
+ final String TIMEOUT_MESSAGE_FORMAT = "%s operation has reached timeout %d milliseconds.";
+
+ private boolean isWaiting = false;
+ private AppcOamStates currentState;
+ long startTimeMs = 0;
+ long timeoutMs = 0;
+ boolean doTimeoutChecking = false;
+
+ String actionName = "Need to be reset";
+ Msg auditMsg;
+ AppcOamStates finalState;
+
+ BaseProcessor myParent;
+ Map<String, Future<?>> bundleNameToFuture = new HashMap<>();
+
+ BaseActionRunnable(BaseProcessor parent) {
+ super(parent.logger, parent.configurationHelper, parent.stateHelper, parent.operationHelper);
+
+ rpc = parent.rpc;
+ commonHeader = parent.commonHeader;
+ startTime = parent.startTime;
+ myParent = parent;
+
+ setTimeoutValues();
+ }
+
+ void setTimeoutValues() {
+ Integer timeoutSeconds = myParent.timeoutSeconds;
+ if (timeoutSeconds == null) {
+ timeoutMs = configurationHelper.getConfig().getIntegerProperty(
+ OAM_OPERATION_TIMEOUT_SECOND, DEFAULT_OAM_OPERATION_TIMEOUT) * 1000;
+ } else {
+ timeoutMs = timeoutSeconds.longValue() * 1000;
+ }
+
+ doTimeoutChecking = timeoutMs != 0;
+ if (doTimeoutChecking) {
+ startTimeMs = startTime.getTime();
+ }
+ logDebug("%s action runnable check timeout (%s) with timeout (%d)ms, and startMs (%d)",
+ rpc.name(), Boolean.toString(doTimeoutChecking), timeoutMs, startTimeMs);
+ }
+
+ @Override
+ public void run() {
+ try {
+ setInitialLogProperties();
+ logDebug(String.format("===========in %s run (waiting: %s)=======",
+ actionName, Boolean.toString(isWaiting)));
+
+ if (isWaiting) {
+ if (!checkState()) {
+ keepWaiting();
+ }
+ } else {
+ if (doAction()) {
+ isWaiting = !checkState();
+ } else {
+ postDoAction(false);
+ }
+ }
+ } catch (Exception e) {
+ logDebug(String.format("%s got exception %s", actionName, e.getMessage()));
+ logger.error(actionName + " exception", e);
+
+ } finally {
+ clearRequestLogProperties();
+ }
+ }
+
+ void keepWaiting() {
+ logDebug(String.format("%s runnable waiting, current state is %s.",
+ actionName, currentState == null ? "null" : currentState.toString()));
+
+ isTimeout("keepWaiting");
+ }
+
+ boolean isTimeout(String parentName) {
+ logDebug(String.format("%s task isTimeout called from %s", actionName, parentName));
+ if (doTimeoutChecking
+ && System.currentTimeMillis() - startTimeMs > timeoutMs) {
+ logger.error(String.format("%s operation timeout (%d) ms has reached, abort with error state.",
+ actionName, timeoutMs));
+
+ setStatus(OAMCommandStatus.TIMEOUT, String.format(TIMEOUT_MESSAGE_FORMAT, rpc.name(), timeoutMs));
+ postAction(AppcOamStates.Error);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set class <b>status</b> to REJECTED with abort message.
+ */
+ void setAbortStatus() {
+ setStatus(OAMCommandStatus.REJECTED, String.format(ABORT_MESSAGE_FORMAT, rpc.name()));
+ }
+
+ /**
+ * Final handling. The thread is cancelled.
+ * @param setState boolean to indicate if set OAM state or not
+ */
+ void postDoAction(boolean setState) {
+ logDebug(String.format("Finished %s task", actionName));
+ }
+
+ /**
+ * Handling for after doAction. does post notification, issue audit log and set OAM state based on input
+ * @param state of AppcOamState to be set as OAM state when it is not null.
+ */
+ void postAction(AppcOamStates state) {
+ operationHelper.sendNotificationMessage(rpc, commonHeader, status);
+
+ if (state != null) {
+ stateHelper.setState(state);
+ }
+
+ auditInfoLog(auditMsg);
+
+ myParent.cancelAsyncTask();
+ }
+
+ /**
+ * Check state
+ * @return true if final state reached, otherwise return false
+ */
+ boolean checkState() {
+ if (isTimeout("checkState")) {
+ myParent.bundleHelper.cancelUnfinished(bundleNameToFuture);
+ return true;
+ }
+
+ if (!myParent.bundleHelper.isAllTaskDone(bundleNameToFuture)) {
+ return false;
+ }
+
+ long failedTask = myParent.bundleHelper.getFailedMetrics(bundleNameToFuture);
+ if (failedTask != 0) {
+ String errorMsg = failedTask + " bundle(s) failed, see logs for details.";
+ setStatus(OAMCommandStatus.UNEXPECTED_ERROR, errorMsg);
+ postAction(AppcOamStates.Error);
+ return true;
+ }
+
+ currentState = stateHelper.getBundlesState();
+ if (currentState == finalState) {
+ setStatus(OAMCommandStatus.SUCCESS);
+ postDoAction(true);
+ return true;
+ }
+ return false;
+ }
+
+ abstract boolean doAction();
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseCommon.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseCommon.java
new file mode 100644
index 000000000..cc725e7b9
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseCommon.java
@@ -0,0 +1,216 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.processor;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.i18n.EELFResourceManager;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.common.header.CommonHeader;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.Status;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.StatusBuilder;
+import org.openecomp.appc.exceptions.InvalidInputException;
+import org.openecomp.appc.exceptions.InvalidStateException;
+import org.openecomp.appc.executor.objects.Params;
+import org.openecomp.appc.i18n.Msg;
+import org.openecomp.appc.logging.LoggingConstants;
+import org.openecomp.appc.logging.LoggingUtils;
+import org.openecomp.appc.oam.AppcOam;
+import org.openecomp.appc.oam.OAMCommandStatus;
+import org.openecomp.appc.oam.util.ConfigurationHelper;
+import org.openecomp.appc.oam.util.OperationHelper;
+import org.openecomp.appc.oam.util.StateHelper;
+import org.slf4j.MDC;
+
+import java.net.InetAddress;
+import java.util.Date;
+
+import static com.att.eelf.configuration.Configuration.MDC_INSTANCE_UUID;
+import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_INSTANCE_ID;
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
+
+/**
+ * Common handling methods of <br>
+ * - BaseProcessor (for REST sync handling) <br>
+ * - BaseActionRunnable (for REST async handling)
+ */
+abstract class BaseCommon {
+ final EELFLogger logger;
+ final ConfigurationHelper configurationHelper;
+ final StateHelper stateHelper;
+ final OperationHelper operationHelper;
+
+ Status status;
+ Date startTime;
+
+ AppcOam.RPC rpc;
+ CommonHeader commonHeader;
+
+ /**
+ * Constructor
+ *
+ * @param eelfLogger for logging
+ * @param configurationHelperIn for property reading
+ * @param stateHelperIn for APP-C OAM state checking
+ * @param operationHelperIn for operational helper
+ */
+ BaseCommon(EELFLogger eelfLogger,
+ ConfigurationHelper configurationHelperIn,
+ StateHelper stateHelperIn,
+ OperationHelper operationHelperIn) {
+ logger = eelfLogger;
+ configurationHelper = configurationHelperIn;
+ stateHelper = stateHelperIn;
+ operationHelper = operationHelperIn;
+ }
+
+ /**
+ * Audit log the passed in message at INFO level.
+ * @param msg the Msg to be audit logged.
+ */
+ void auditInfoLog(Msg msg) {
+ LoggingUtils.auditInfo(startTime.toInstant(),
+ new Date(System.currentTimeMillis()).toInstant(),
+ String.valueOf(status.getCode()),
+ status.getMessage(),
+ getClass().getCanonicalName(),
+ msg,
+ configurationHelper.getAppcName(),
+ stateHelper.getCurrentOamState().toString()
+ );
+ }
+
+ /**
+ * Set MDC properties.
+ */
+ void setInitialLogProperties() {
+ MDC.put(MDC_KEY_REQUEST_ID, commonHeader.getRequestId());
+ MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, commonHeader.getOriginatorId());
+ MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
+ MDC.put(MDC_SERVICE_NAME, rpc.name());
+ try {
+ //!!!Don't change the following to a .getHostName() again please. It's wrong!MDC.put(MDC_SERVER_FQDN,
+ // InetAddress.getLocalHost().getCanonicalHostName());
+ MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName());
+ MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
+ MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
+ } catch (Exception e) {
+ logger.error("MDC constant error", e);
+ }
+ }
+
+ /**
+ * Clear MDC properties.
+ */
+ void clearRequestLogProperties() {
+ try {
+ MDC.remove(MDC_KEY_REQUEST_ID);
+ MDC.remove(MDC_SERVICE_INSTANCE_ID);
+ MDC.remove(MDC_SERVICE_NAME);
+ MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
+ MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
+ } catch (Exception e) {
+ logger.error("Unable to clear the Request Log properties" + e.getMessage());
+ }
+ }
+
+ /**
+ * Set class <b>status</b> by calling setStatus(OAMCommandStatus, Params) with null paramter.
+ * @see #setStatus(OAMCommandStatus, String)
+ *
+ * @param oamCommandStatus of the to be set new state
+ */
+ void setStatus(OAMCommandStatus oamCommandStatus) {
+ setStatus(oamCommandStatus, null);
+ }
+
+ /**
+ * Create Status based on the passed in parameter, then set the class <b>status</b> with it.
+ *
+ * @param oamCommandStatus of the current OAM command status
+ * @param message to be set in the new status
+ */
+ void setStatus(OAMCommandStatus oamCommandStatus, String message) {
+ Params params = new Params().addParam("errorMsg", message);
+
+ StatusBuilder statusBuilder = new StatusBuilder();
+ statusBuilder.setCode(oamCommandStatus.getResponseCode());
+ if (params != null) {
+ statusBuilder.setMessage(oamCommandStatus.getFormattedMessage(params));
+ } else {
+ statusBuilder.setMessage(oamCommandStatus.getResponseMessage());
+ }
+
+ status = statusBuilder.build();
+ }
+
+ /**
+ * Set class <b>status</b> with error status calculated from the passed in paremeter
+ * and audit log the error message.
+ * @param t of the erro Throwable.
+ */
+ void setErrorStatus(Throwable t) {
+ final String appName = configurationHelper.getAppcName();
+ String exceptionMessage = t.getMessage() != null ? t.getMessage() : t.toString();
+
+ OAMCommandStatus oamCommandStatus;
+ String errorMessage;
+ if (t instanceof InvalidInputException) {
+ oamCommandStatus = OAMCommandStatus.INVALID_PARAMETER;
+ errorMessage = EELFResourceManager.format(Msg.OAM_OPERATION_INVALID_INPUT, t.getMessage());
+ } else if (t instanceof InvalidStateException) {
+ exceptionMessage = String.format(AppcOam.INVALID_STATE_MESSAGE_FORMAT,
+ rpc.getAppcOperation(), appName, stateHelper.getCurrentOamState());
+ oamCommandStatus = OAMCommandStatus.REJECTED;
+ errorMessage = EELFResourceManager.format(Msg.INVALID_STATE_TRANSITION, exceptionMessage);
+ } else {
+ oamCommandStatus = OAMCommandStatus.UNEXPECTED_ERROR;
+ errorMessage = EELFResourceManager.format(Msg.OAM_OPERATION_EXCEPTION, t,
+ appName, t.getClass().getSimpleName(), rpc.name(), exceptionMessage);
+ }
+
+ setStatus(oamCommandStatus, exceptionMessage);
+
+ LoggingUtils.logErrorMessage(
+ String.valueOf(status.getCode()),
+ status.getMessage(),
+ LoggingConstants.TargetNames.APPC,
+ LoggingConstants.TargetNames.APPC_OAM_PROVIDER,
+ errorMessage,
+ AppcOam.class.getCanonicalName());
+ }
+
+ /**
+ * Genral debug log when debug logging level is enabled.
+ * @param message of the log message format
+ * @param args of the objects listed in the message format
+ */
+ void logDebug(String message, Object... args) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format(message, args));
+ }
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseProcessor.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseProcessor.java
new file mode 100644
index 000000000..6c7011111
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/BaseProcessor.java
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.processor;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.Status;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.exceptions.InvalidInputException;
+import org.openecomp.appc.exceptions.InvalidStateException;
+import org.openecomp.appc.i18n.Msg;
+import org.openecomp.appc.oam.OAMCommandStatus;
+import org.openecomp.appc.oam.util.AsyncTaskHelper;
+import org.openecomp.appc.oam.util.BundleHelper;
+import org.openecomp.appc.oam.util.ConfigurationHelper;
+import org.openecomp.appc.oam.util.OperationHelper;
+import org.openecomp.appc.oam.util.StateHelper;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
+
+import java.util.Date;
+import java.util.concurrent.Future;
+
+/**
+ * Base processor for OAM APIs, such as maintenance mode, restart, start and stop API.
+ *
+ * <p>This class holds the general API request sync handling methods for all OAM APIs.
+ * <p>Specific API processor will overwrite the general methods to add specific behaviors.
+ */
+public abstract class BaseProcessor extends BaseCommon {
+ final AsyncTaskHelper asyncTaskHelper;
+ final BundleHelper bundleHelper;
+
+
+ Integer timeoutSeconds;
+ Msg auditMsg;
+ Runnable runnable;
+ private Future<?> scheduledRunnable = null;
+
+ /**
+ * Constructor
+ *
+ * @param eelfLogger for logging
+ * @param configurationHelperIn for property reading
+ * @param stateHelperIn for APP-C OAM state checking
+ * @param asyncTaskHelperIn for scheduling async task
+ * @param operationHelperIn for operational helper
+ */
+ BaseProcessor(EELFLogger eelfLogger,
+ ConfigurationHelper configurationHelperIn,
+ StateHelper stateHelperIn,
+ AsyncTaskHelper asyncTaskHelperIn,
+ OperationHelper operationHelperIn) {
+ super(eelfLogger, configurationHelperIn, stateHelperIn, operationHelperIn);
+
+ asyncTaskHelper = asyncTaskHelperIn;
+ bundleHelper = new BundleHelper(eelfLogger, configurationHelper, stateHelper);
+ }
+
+ /**
+ * Process synch handling and schedule asynch task
+ *
+ * @param requestInput of REST API request
+ * @return Status of new APP-C OAM state
+ */
+ public Status processRequest(final Object requestInput) {
+ startTime = new Date();
+ commonHeader = operationHelper.getCommonHeader(requestInput);
+ setStatus(OAMCommandStatus.ACCEPTED);
+
+ try {
+ preProcess(requestInput);
+ timeoutSeconds = operationHelper.getParamRequestTimeout(requestInput);
+ scheduleAsyncTask();
+ } catch (Throwable t) {
+ setErrorStatus(t);
+ } finally {
+ postProcess();
+ }
+
+ return status;
+ }
+
+ /**
+ * Preprocess before actual handling of the REST API call. Does:
+ * <p> - commonHeader validation
+ * <p> - get NextState as well as validate if next state is valid
+ * <p> - set logging properties
+ * <p> - set appcCurrentState to next state
+ *
+ * @throws InvalidInputException when commonHeader validation failed
+ * @throws APPCException when state validation failed
+ */
+ protected void preProcess(final Object requestInput)
+ throws InvalidInputException, APPCException, InvalidStateException {
+ operationHelper.isInputValid(requestInput);
+
+ AppcOamStates nextState = operationHelper.getNextState(
+ rpc.getAppcOperation(), stateHelper.getCurrentOamState());
+ setInitialLogProperties();
+ stateHelper.setState(nextState);
+ }
+
+ /**
+ * Post process includes audit logging as well as clear MDC properties.
+ */
+ private void postProcess() {
+ auditInfoLog(auditMsg);
+ clearRequestLogProperties();
+ }
+
+ /**
+ * Schedule async task through AsyncTaskHelper.
+ */
+ protected void scheduleAsyncTask() {
+ if (runnable == null) {
+ logger.error(String.format(
+ "Skipped schedule async task for rpc(%s) due to runnable is null", rpc.name()));
+ return;
+ }
+
+ scheduledRunnable = asyncTaskHelper.scheduleAsyncTask(rpc, runnable);
+ }
+
+ /**
+ * Check if current running task is the same as schedule task
+ * @return true if they are the same, otherwise false.
+ */
+ boolean isSameAsyncTask() {
+ return asyncTaskHelper.getCurrentAsyncTask() == scheduledRunnable;
+ }
+
+ /**
+ * Cancel schedueled async task through AsyncTaskHelper
+ */
+ void cancelAsyncTask() {
+ if (scheduledRunnable == null) {
+ logger.error(String.format(
+ "Skipped cancel schedule async task for rpc(%s) due to scheduledRunnable is null", rpc.name()));
+ return;
+ }
+
+ asyncTaskHelper.cancelAsyncTask(scheduledRunnable);
+ scheduledRunnable = null;
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamMmodeProcessor.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamMmodeProcessor.java
new file mode 100644
index 000000000..d0d946aed
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamMmodeProcessor.java
@@ -0,0 +1,163 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.processor;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.exceptions.InvalidInputException;
+import org.openecomp.appc.exceptions.InvalidStateException;
+import org.openecomp.appc.i18n.Msg;
+import org.openecomp.appc.oam.AppcOam;
+import org.openecomp.appc.oam.OAMCommandStatus;
+import org.openecomp.appc.oam.util.AsyncTaskHelper;
+import org.openecomp.appc.oam.util.ConfigurationHelper;
+import org.openecomp.appc.oam.util.OperationHelper;
+import org.openecomp.appc.oam.util.StateHelper;
+import org.openecomp.appc.requesthandler.LCMStateManager;
+import org.openecomp.appc.requesthandler.RequestHandler;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
+
+/**
+ * Processor to handle maintenance mode OAM API.
+ */
+public class OamMmodeProcessor extends BaseProcessor {
+ /**
+ * Constructor
+ *
+ * @param eelfLogger for logging
+ * @param configurationHelper for property reading
+ * @param stateHelper for APP-C OAM state checking
+ * @param asyncTaskHelper for scheduling async task
+ * @param operationHelper for operational helper
+ */
+ public OamMmodeProcessor(EELFLogger eelfLogger,
+ ConfigurationHelper configurationHelper,
+ StateHelper stateHelper,
+ AsyncTaskHelper asyncTaskHelper,
+ OperationHelper operationHelper) {
+ super(eelfLogger, configurationHelper, stateHelper, asyncTaskHelper, operationHelper);
+
+ rpc = AppcOam.RPC.maintenance_mode;
+ auditMsg = Msg.OAM_OPERATION_ENTERING_MAINTENANCE_MODE;
+ }
+
+ @Override
+ protected void preProcess(final Object requestInput)
+ throws InvalidInputException, InvalidStateException, APPCException {
+ super.preProcess(requestInput);
+
+ //Close the gate so that no more new LCM request will be excepted.
+ LCMStateManager lcmStateManager = operationHelper.getService(LCMStateManager.class);
+ lcmStateManager.disableLCMOperations();
+ }
+
+ @Override
+ protected void scheduleAsyncTask() {
+ runnable = new MyRunnable(this);
+ super.scheduleAsyncTask();
+ }
+
+ /**
+ * This runnable does the async handling for the maintenance mode REST API, and will be scheduled to run
+ * until terminating condition reaches.
+ *
+ * <p>The runnable will conintue run if: <br>
+ * - the runnable is not canceled outside <br>
+ * - the in progress LCM request count is not zero<br>
+ * <p> When LCM request count reaches to zero, this runnable will: <br>
+ * - post message through operatonHelper <br>
+ * - set APP-C OAM state to maintenance mode <br>
+ * - audit log the state <br>
+ * - terminate this runnable itself <br>
+ */
+ class MyRunnable extends BaseActionRunnable {
+ private int inprogressRequestCount;
+
+ MyRunnable(BaseProcessor parent) {
+ super(parent);
+
+ actionName = "OAM Maintanence mode";
+ auditMsg = Msg.OAM_OPERATION_MAINTENANCE_MODE;
+ finalState = AppcOamStates.MaintenanceMode;
+ }
+
+ @Override
+ boolean doAction() {
+ // always return true, so that we can check the LCM request count
+ return true;
+ }
+
+ @Override
+ boolean checkState() {
+ logDebug(String.format("Executing %s task", actionName));
+
+ if (!myParent.isSameAsyncTask()) {
+ // cancel myself if I am not the current backgroundOamTask
+ myParent.cancelAsyncTask();
+ logDebug(String.format("Finished %s task due to task removed", actionName));
+ return true;
+ }
+
+ boolean hasError = false;
+ try {
+ inprogressRequestCount = getInprogressLCMRequestCount();
+ if (inprogressRequestCount > 0) {
+ // if there are still LCM request in progress, keep waiting
+ return false;
+ }
+
+ setStatus(OAMCommandStatus.SUCCESS);
+ } catch (Throwable t) {
+ setErrorStatus(t);
+ hasError = true;
+ }
+
+ postAction(hasError ? AppcOamStates.Error : finalState);
+ return true;
+ }
+
+ /**
+ * Get in progress LCM request count through RequestHandler.
+ * @return thecount of in progress LCM request
+ * @throws APPCException if RequestHandler throws it.
+ */
+ private int getInprogressLCMRequestCount() throws APPCException {
+ RequestHandler requestHandler = operationHelper.getService(RequestHandler.class);
+
+ if (requestHandler == null) {
+ return 0;
+ }
+
+ return requestHandler.getInprogressRequestCount();
+ }
+
+ @Override
+ void keepWaiting() {
+ logDebug("The application '%s' has '%s' outstanding LCM request to complete" +
+ " before coming to a complete maintenance_mode.",
+ configurationHelper.getAppcName(), inprogressRequestCount);
+ }
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamRestartProcessor.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamRestartProcessor.java
new file mode 100644
index 000000000..529d25004
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamRestartProcessor.java
@@ -0,0 +1,207 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.processor;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.i18n.Msg;
+import org.openecomp.appc.oam.AppcOam;
+import org.openecomp.appc.oam.util.AsyncTaskHelper;
+import org.openecomp.appc.oam.util.ConfigurationHelper;
+import org.openecomp.appc.oam.util.OperationHelper;
+import org.openecomp.appc.oam.util.StateHelper;
+import org.openecomp.appc.requesthandler.LCMStateManager;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
+
+/**
+ * Processor to handle restart OAM API.
+ */
+public class OamRestartProcessor extends BaseProcessor {
+ /**
+ * Action phases:
+ * <br> -ToStop: call bundles stop
+ * <br> -Stopped: check if all bundle state reached stopped
+ * <br> -ToStart: call bundles start
+ * <br> -Started: action is full completed
+ * <br> -Timeout: indication of timeout reached
+ */
+ private enum ActionPhases {
+ ToStop,
+ Stopped,
+ ToStart,
+ Started,
+ Timeout
+ }
+
+ /**
+ * Constructor
+ *
+ * @param eelfLogger for logging
+ * @param configurationHelper for property reading
+ * @param stateHelper for APP-C OAM state checking
+ * @param asyncTaskHelper for scheduling async task
+ * @param operationHelper for operational helper
+ */
+ public OamRestartProcessor(EELFLogger eelfLogger,
+ ConfigurationHelper configurationHelper,
+ StateHelper stateHelper,
+ AsyncTaskHelper asyncTaskHelper,
+ OperationHelper operationHelper) {
+ super(eelfLogger, configurationHelper, stateHelper, asyncTaskHelper, operationHelper);
+
+ rpc = AppcOam.RPC.restart;
+ auditMsg = Msg.OAM_OPERATION_RESTARTING;
+ }
+
+ @Override
+ protected void scheduleAsyncTask() {
+ runnable = new MyRunnable(this);
+ super.scheduleAsyncTask();
+ }
+
+ /**
+ * This runnable does the async handling for the restart REST API. And it will be scheduled to run one time.
+ *
+ * <p>This runnable will the following operations: <br>
+ * - do APP-C OAM bundle stop and then start through BundlerHelper<br>
+ * - and always enable LCM operation handling (which can be disabled through maintenance mode API).<br>
+ * <p>Once above operations are done, the runnale will <br>
+ * - post message through operatonHelper <br>
+ * - set APP-C OAM state to started <br>
+ * - audit log the state <br>
+ */
+ class MyRunnable extends BaseActionRunnable {
+
+ ActionPhases currentPhase = ActionPhases.ToStop;
+ private LCMStateManager lcmStateManager;
+
+ MyRunnable(BaseProcessor parent) {
+ super(parent);
+
+ actionName = "OAM Restart";
+ auditMsg = Msg.OAM_OPERATION_RESTARTED;
+ finalState = AppcOamStates.Started;
+ }
+
+ /**
+ * Do restart action, include stop then start and always enable LCM operation.
+ * @return true if action is successful, false when aciton is failed or aborted
+ */
+ @Override
+ boolean doAction() {
+ logDebug(String.format("Executing %s task at phase (%s)",
+ actionName, currentPhase == null ? "null" : currentPhase.name()));
+
+ boolean isBundleOperationCompleted = true;
+ try {
+ switch (currentPhase) {
+ case ToStop:
+ isBundleOperationCompleted = bundleHelper.bundleOperations(
+ AppcOam.RPC.stop, bundleNameToFuture, myParent.asyncTaskHelper);
+ currentPhase = ActionPhases.Stopped;
+ break;
+ case Stopped:
+ // check state
+ AppcOamStates currentState = stateHelper.getBundlesState();
+ if (currentState == AppcOamStates.Stopped) {
+ currentPhase = ActionPhases.ToStart;
+ } else {
+ logDebug(String.format("%s task is waiting in stopped phase, current state is %s",
+ actionName, currentState));
+ }
+ break;
+ case ToStart:
+ isBundleOperationCompleted = bundleHelper.bundleOperations(
+ AppcOam.RPC.start, bundleNameToFuture, myParent.asyncTaskHelper);
+ currentPhase = ActionPhases.Started;
+ break;
+ case Timeout:
+ // do nothing
+ break;
+ default:
+ // Should not reach log it and return false;
+ logger.error("%s task doAction reached %s phase. not supported. return false.",
+ actionName, currentPhase.name());
+ stateHelper.setState(AppcOamStates.Error);
+ return false;
+ }
+
+ if (isTimeout("restart doAction")) {
+ currentPhase = ActionPhases.Timeout;
+ return true;
+ }
+ if (isBundleOperationCompleted) {
+ return true;
+ }
+
+ setAbortStatus();
+ } catch (APPCException e) {
+ setErrorStatus(e);
+ stateHelper.setState(AppcOamStates.Error);
+ }
+
+ return false;
+ }
+
+ /**
+ * With additional to get the LCMStateManager service
+ * @see BaseActionRunnable#checkState()
+ */
+ @Override
+ boolean checkState() {
+ switch (currentPhase) {
+ case Started:
+ try {
+ lcmStateManager = operationHelper.getService(LCMStateManager.class);
+ return super.checkState();
+ } catch (APPCException e) {
+ logDebug("LCMStateManager is not available.");
+ }
+ break;
+ default:
+ // in all the other ActionPhase, we want the run go back to doAction
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Final handling. The thread is cancelled.
+ * @param setState boolean to indicate if set OAM state or not
+ */
+ @Override
+ void postDoAction(boolean setState) {
+ AppcOamStates newState = null;
+ if (setState) {
+ logDebug("Always enable LCM operation");
+ lcmStateManager.enableLCMOperations();
+ newState = finalState;
+ }
+ postAction(newState);
+ super.postDoAction(setState);
+ }
+
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamStartProcessor.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamStartProcessor.java
new file mode 100644
index 000000000..0060bfcae
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamStartProcessor.java
@@ -0,0 +1,151 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.processor;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.i18n.Msg;
+import org.openecomp.appc.oam.AppcOam;
+import org.openecomp.appc.oam.util.AsyncTaskHelper;
+import org.openecomp.appc.oam.util.ConfigurationHelper;
+import org.openecomp.appc.oam.util.OperationHelper;
+import org.openecomp.appc.oam.util.StateHelper;
+import org.openecomp.appc.requesthandler.LCMStateManager;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
+
+/**
+ * Processor to handle start OAM API.
+ */
+public class OamStartProcessor extends BaseProcessor {
+
+ /**
+ * Constructor
+ *
+ * @param eelfLogger for logging
+ * @param configurationHelper for property reading
+ * @param stateHelper for APP-C OAM state checking
+ * @param asyncTaskHelper for scheduling async task
+ * @param operationHelper for operational helper
+ */
+ public OamStartProcessor(EELFLogger eelfLogger,
+ ConfigurationHelper configurationHelper,
+ StateHelper stateHelper,
+ AsyncTaskHelper asyncTaskHelper,
+ OperationHelper operationHelper) {
+ super(eelfLogger, configurationHelper, stateHelper, asyncTaskHelper, operationHelper);
+
+ rpc = AppcOam.RPC.start;
+ auditMsg = Msg.OAM_OPERATION_STARTING;
+ }
+
+ @Override
+ protected void scheduleAsyncTask() {
+ runnable = new MyRunnable(this);
+ super.scheduleAsyncTask();
+ }
+
+ /**
+ * This runnable does the async handling for the start REST API. And it will be scheduled to run one time.
+ *
+ * <p>This runnable will the following operations: <br>
+ * - do APP-C OAM bundle start through BundlerHelper<br>
+ * - and always enable LCM operation handling (which can be disabled through maintenance mode API).<br>
+ * <p>Once above operations are done, the runnale will <br>
+ * - post message through operatonHelper <br>
+ * - set APP-C OAM state to started <br>
+ * - audit log the state <br>
+ */
+ class MyRunnable extends BaseActionRunnable {
+
+ private LCMStateManager lcmStateManager;
+
+ MyRunnable(BaseProcessor parent) {
+ super(parent);
+ actionName = "OAM Start";
+ auditMsg = Msg.OAM_OPERATION_STARTED;
+ finalState = AppcOamStates.Started;
+ }
+
+ /**
+ * Do start action, include start bundle if needed and always enable LCM operation.
+ * @return true if action is successful, false when aciton is failed or aborted
+ */
+ @Override
+ boolean doAction() {
+ logDebug(String.format("Executing %s task", actionName));
+
+ boolean isBundleOperationCompleted = true;
+ try {
+ if (stateHelper.getState() != AppcOamStates.Started) {
+ logDebug("Start - APPC OAM state is not started, start the bundles");
+ isBundleOperationCompleted = bundleHelper.bundleOperations(
+ rpc, bundleNameToFuture, myParent.asyncTaskHelper);
+ }
+
+ if (isBundleOperationCompleted) {
+ return true;
+ }
+
+ setAbortStatus();
+ } catch (APPCException e) {
+ setErrorStatus(e);
+ stateHelper.setState(AppcOamStates.Error);
+ }
+
+ return false;
+ }
+
+ /**
+ * With additional to get the LCMStateManager service
+ * @see BaseActionRunnable#checkState()
+ */
+ @Override
+ boolean checkState() {
+ try {
+ lcmStateManager = operationHelper.getService(LCMStateManager.class);
+ return super.checkState();
+ } catch (APPCException e) {
+ logDebug("LCMStateManager is not available.");
+ return false;
+ }
+ }
+
+ /**
+ * Final handling
+ * @param setState boolean to indicate if set OAM state or not
+ */
+ @Override
+ void postDoAction(boolean setState) {
+ AppcOamStates newState = null;
+ if (setState) {
+ logDebug("Always enable LCM operation");
+ lcmStateManager.enableLCMOperations();
+ newState = finalState;
+ }
+ postAction(newState);
+ super.postDoAction(setState);
+ }
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamStopProcessor.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamStopProcessor.java
new file mode 100644
index 000000000..d81901638
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/processor/OamStopProcessor.java
@@ -0,0 +1,120 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.processor;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.i18n.Msg;
+import org.openecomp.appc.oam.AppcOam;
+import org.openecomp.appc.oam.util.AsyncTaskHelper;
+import org.openecomp.appc.oam.util.ConfigurationHelper;
+import org.openecomp.appc.oam.util.OperationHelper;
+import org.openecomp.appc.oam.util.StateHelper;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
+
+/**
+ * Processor to handle stop OAM API.
+ */
+public class OamStopProcessor extends BaseProcessor {
+ /**
+ * Constructor
+ *
+ * @param eelfLogger for logging
+ * @param configurationHelper for property reading
+ * @param stateHelper for APP-C OAM state checking
+ * @param asyncTaskHelper for scheduling async task
+ * @param operationHelper for operational helper
+ */
+ public OamStopProcessor(EELFLogger eelfLogger,
+ ConfigurationHelper configurationHelper,
+ StateHelper stateHelper,
+ AsyncTaskHelper asyncTaskHelper,
+ OperationHelper operationHelper) {
+ super(eelfLogger, configurationHelper, stateHelper, asyncTaskHelper, operationHelper);
+
+ rpc = AppcOam.RPC.stop;
+ auditMsg = Msg.OAM_OPERATION_STOPPING;
+ }
+
+
+ @Override
+ protected void scheduleAsyncTask() {
+ runnable = new MyRunnable(this);
+ super.scheduleAsyncTask();
+ }
+
+ /**
+ * This runnable does the async handling for the stop REST API. And it will be scheduled to run one time.
+ *
+ * <p>This runnable will the following operations: <br>
+ * - do APP-C OAM bundle stop and then refresh through BundlerHelper<br>
+ * <p>Once above operations are done, the runnale will <br>
+ * - post message through operatonHelper <br>
+ * - set APP-C OAM state to started <br>
+ * - audit log the state <br>
+ */
+ class MyRunnable extends BaseActionRunnable {
+
+ MyRunnable(BaseProcessor parent) {
+ super(parent);
+ actionName = "OAM Stop";
+ auditMsg = Msg.OAM_OPERATION_STOPPED;
+ finalState = AppcOamStates.Stopped;
+ }
+
+ /**
+ * Do stop action, include stop bundle .
+ * @return true if action is successful, false when aciton is failed.
+ */
+ @Override
+ boolean doAction() {
+ logDebug(String.format("Executing %s task", actionName));
+
+ try {
+ boolean isBundleOperationCompleted = bundleHelper.bundleOperations(
+ rpc, bundleNameToFuture, myParent.asyncTaskHelper);
+ if (isBundleOperationCompleted) {
+ return true;
+ }
+
+ setAbortStatus();
+ } catch (APPCException e) {
+ setErrorStatus(e);
+ stateHelper.setState(AppcOamStates.Error);
+ }
+ return false;
+ }
+
+ /**
+ * Final handling
+ * @param setState boolean to indicate if set OAM state or not
+ */
+ @Override
+ void postDoAction(boolean setState) {
+ postAction(setState ? finalState : null);
+ super.postDoAction(setState);
+ }
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/AsyncTaskHelper.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/AsyncTaskHelper.java
new file mode 100644
index 000000000..ff28e995a
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/AsyncTaskHelper.java
@@ -0,0 +1,165 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.openecomp.appc.oam.AppcOam;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Utility class provides general async task related help.
+ */
+@SuppressWarnings("unchecked")
+public class AsyncTaskHelper {
+ final int MMODE_TASK_DELAY = 10000;
+ final int COMMON_INITIAL_DELAY = 0;
+ final int COMMON_INTERVAL = 1000;
+
+ private final EELFLogger logger;
+ private final ScheduledExecutorService scheduledExecutorService;
+ private final ThreadPoolExecutor bundleOperationService;
+
+ /** Reference to the Async task */
+ private volatile Future<?> backgroundOamTask;
+
+ /**
+ * Constructor
+ * @param eelfLogger of the logger
+ */
+ public AsyncTaskHelper(EELFLogger eelfLogger) {
+ logger = eelfLogger;
+
+ scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(
+ (runnable) -> {
+ Bundle bundle = FrameworkUtil.getBundle(AppcOam.class);
+ return new Thread(runnable, bundle.getSymbolicName() + " scheduledExecutor");
+ }
+ );
+
+ bundleOperationService = new ThreadPoolExecutor(
+ 0,
+ 10,
+ 10,
+ TimeUnit.SECONDS,
+ new LinkedBlockingQueue(),// BlockingQueue<Runnable> workQueue
+ (runnable) -> new Thread(runnable, "OAM bundler operation executor")//ThreadFactory
+ );
+ }
+
+ void addThreadsToPool() {
+ bundleOperationService.setCorePoolSize(bundleOperationService.getMaximumPoolSize());
+ }
+
+ void removeThreadsFromPoolWhenDone() {
+ bundleOperationService.setCorePoolSize(0);
+ }
+
+ /**
+ * Terminate the class <bS>ScheduledExecutorService</b>
+ */
+ public void close() {
+ logDebug("Start shutdown scheduleExcutorService.");
+ scheduledExecutorService.shutdown();
+ bundleOperationService.shutdown();
+ logDebug("Completed shutdown scheduleExcutorService.");
+ }
+
+ /**
+ * Get current async task refernce
+ * @return the class <b>backgroundOamTask</b>
+ */
+ public Future<?> getCurrentAsyncTask() {
+ return backgroundOamTask;
+ }
+
+ /**
+ * Schedule a service for async task with the passed in parameters
+ * @param rpc of the REST API call, decides how to schedule the service
+ * @param runnable of the to be scheduled service.
+ * @return the refernce of the scheduled task
+ */
+ public Future<?> scheduleAsyncTask(final AppcOam.RPC rpc, final Runnable runnable) {
+ int initialDelay, interval;
+ switch (rpc) {
+ case maintenance_mode:
+ initialDelay = interval =MMODE_TASK_DELAY;
+ break;
+ case start:
+ case stop:
+ case restart:
+ initialDelay = COMMON_INITIAL_DELAY;
+ interval = COMMON_INTERVAL;
+ break;
+ default:
+ // should not get here. Log it and return null
+ logDebug(String.format("Cannot scheudle task for unsupported RPC(%s).", rpc.name()));
+ return null;
+ }
+
+ // Always cancel existing async task
+ if (backgroundOamTask != null) {
+ backgroundOamTask.cancel(true);
+ }
+ backgroundOamTask = scheduledExecutorService.scheduleWithFixedDelay(
+ runnable, initialDelay, interval, TimeUnit.MILLISECONDS);
+
+ return backgroundOamTask;
+ }
+
+ Future<?> submitBundleLcOperation(final Callable callable) {
+ return bundleOperationService.submit(callable);
+ }
+
+ /**
+ * Cancle a previously schedule task. If the task is the same as backgroundOamTask, set it to null.
+ * @param task to be canceled
+ */
+ public void cancelAsyncTask(Future<?> task) {
+ task.cancel(false);
+ if (task == backgroundOamTask) {
+ backgroundOamTask = null;
+ }
+ }
+
+ /**
+ * Genral debug log when debug logging level is enabled.
+ * @param message of the log message format
+ * @param args of the objects listed in the message format
+ */
+ private void logDebug(String message, Object... args) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format(message, args));
+ }
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/BundleFilter.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/BundleFilter.java
new file mode 100644
index 000000000..1e9f9b6a1
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/BundleFilter.java
@@ -0,0 +1,128 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.util;
+
+import org.osgi.framework.Bundle;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+
+
+/**
+ *
+ * Utility Class that splits a given bundleSet into two sets: bundleToStopSet and
+ * bundleToNotStopSet
+ *
+ * The bundleToStopSet is defined as: all bundles which match at least one of
+ * the stopRegexes but exceptRegexes none of the
+ *
+ * The bundleToNotStopSet is defined as all bundles which are not a member of
+ * the bundleToStopSet
+ *
+ */
+class BundleFilter {
+
+ private final Map<String, Bundle> bundleToStopSet;
+ private final Map<String, Bundle> bundleToNotStopSet;
+
+
+ /**
+ * BundleFilter a bundle filter
+ * @param stopRegexes - An array of regular expression used to pick out which bundles are candidates for stopping
+ * @param exceptRegexes - An array of regular expression used to override which bundles are candidates for stopping
+ * @param bundles - An array of the bundle to be split into {@link #getBundlesToStop()} {@link #getBundlesToNotStop()}
+ */
+ BundleFilter(String[] stopRegexes, String[] exceptRegexes, Bundle[] bundles) {
+
+ Pattern[] stopPatterns = toPattern(stopRegexes);
+ Pattern[] exceptPatterns = toPattern(exceptRegexes);
+
+ Map<String, Bundle> bundleToStop = new HashMap<>();
+ Map<String, Bundle> bundleToNotStop = new HashMap<>();
+
+ for (Bundle bundle : bundles) {
+ String symbolicName = bundle.getSymbolicName();
+ if (isMatch(symbolicName,stopPatterns) && !isMatch(symbolicName,exceptPatterns)) {
+ bundleToStop.put(symbolicName, bundle);
+ } else {
+ bundleToNotStop.put(symbolicName, bundle);
+ }
+ }
+
+ this.bundleToStopSet = Collections.unmodifiableMap(bundleToStop);
+ this.bundleToNotStopSet = Collections.unmodifiableMap(bundleToNotStop);
+ }
+
+ /**
+ * Determines if the value matches any of the regular expressions.
+ *
+ * @param value
+ * - the value that is to be matched
+ * @param patterns
+ * - the array of {@link Pattern} to match the value against
+ * @return boolean true if there is a match
+ */
+ private boolean isMatch(String value,Pattern[] patterns) {
+ for (Pattern pattern : patterns) {
+ if (pattern.matcher(value).matches()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * This method converts an Array of regular expression in String form into a
+ * Array of {@link Pattern}
+ *
+ * @param regex
+ * - A string array of regular expressions
+ * @return Pattern Array of compiled regular expressions
+ */
+ private Pattern[] toPattern(String[] regex) {
+ Pattern[] pattern = new Pattern[regex.length];
+ for (int i = 0; i < regex.length; i++ ) {
+ pattern[i] = Pattern.compile(regex[i]);
+ }
+ return pattern;
+ }
+
+
+ /**@return Map of bundles that are to be stopped */
+ Map<String, Bundle> getBundlesToStop(){
+ return bundleToStopSet;
+ }
+
+ /**
+ *
+ * @return Map of bundles that are not to be stopped
+ */
+ Map<String, Bundle> getBundlesToNotStop() {
+ return bundleToNotStopSet;
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/BundleHelper.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/BundleHelper.java
new file mode 100644
index 000000000..7fbb3c453
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/BundleHelper.java
@@ -0,0 +1,265 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.apache.commons.lang3.ArrayUtils;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.oam.AppcOam;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkUtil;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+
+/**
+ * Utility class provides general bundle operational helps.
+ */
+public class BundleHelper {
+ private final static String PROP_BUNDLE_TO_STOP = "appc.OAM.ToStop.properties";
+ private final static String PROP_BUNDLES_TO_NOT_STOP = "appc.OAM.ToNotStop.properties";
+
+ private final EELFLogger logger;
+ private final StateHelper stateHelper;
+ private final ConfigurationHelper configurationHelper;
+
+ /**
+ * Constructor
+ *
+ * @param eelfLogger of the logger
+ * @param configurationHelperIn of ConfigurationHelper instance
+ * @param stateHelperIn of StateHelper instance
+ */
+ public BundleHelper(EELFLogger eelfLogger,
+ ConfigurationHelper configurationHelperIn,
+ StateHelper stateHelperIn) {
+ logger = eelfLogger;
+ configurationHelper = configurationHelperIn;
+ stateHelper = stateHelperIn;
+ }
+
+ /**
+ * Handle bundle operations, such as stop or start bundle.
+ *
+ * @param rpc enum indicate if the operation is to stop, start or restart
+ * @return boolean to indicate if the operation is successful (true) or failed (false)
+ * @throws APPCException when error occurs
+ */
+ public boolean bundleOperations(AppcOam.RPC rpc,
+ Map<String, Future<?>> threads,
+ AsyncTaskHelper taskHelper)
+ throws APPCException {
+ long mStartTime = System.currentTimeMillis();
+ logDebug(String.format("Entering OAM bundleOperations with rpc (%s).", rpc.name()));
+
+ String action = rpc.getAppcOperation().toString();
+ if (rpc != AppcOam.RPC.stop && rpc != AppcOam.RPC.start) {
+ throw new APPCException("rpc(" + rpc + ") is not supported by bundleOperation.");
+ }
+
+ AppcOamStates originalState = stateHelper.getState();
+
+ boolean isBundleOperationComplete = true;
+
+ Map<String, Bundle> appcLcmBundles = getAppcLcmBundles();
+ taskHelper.addThreadsToPool();
+ for (Map.Entry<String, Bundle> bundleEntry : appcLcmBundles.entrySet()) {
+ String bundleName = bundleEntry.getKey();
+ Bundle bundle = bundleEntry.getValue();
+
+ logDebug("OAM launch thread for %s bundle %s", action, bundleName);
+ if (rpc == AppcOam.RPC.start) {
+ // Abort in the interruption case.
+ // such as when a Stop request is receive while APPC is still trying to Start Up.
+ if (!stateHelper.isSameState(originalState)) {
+ logger.warn("OAM %s bundle operation aborted since OAM state is no longer %s!",
+ originalState.name());
+ isBundleOperationComplete = false;
+ break;
+ }
+ }
+
+ threads.put(bundleName,
+ taskHelper.submitBundleLcOperation(new BundleTask(rpc, bundle)));
+ }
+ taskHelper.removeThreadsFromPoolWhenDone();
+
+ logDebug(String.format("Leaving OAM bundleOperations with rpc (%s) with complete(%s), elasped (%d) ms.",
+ rpc.name(), Boolean.toString(isBundleOperationComplete), getElaspeTimeMs(mStartTime)));
+
+ return isBundleOperationComplete;
+ }
+
+ private long getElaspeTimeMs(long mStartTime) {
+ return System.currentTimeMillis() - mStartTime;
+ }
+
+ /**
+ * Check if all BundleTasks are completed
+ * @param bundleNameFutureMap with bundler name and BundleTask Future object
+ * @return true if all are done, otherwise, false
+ */
+ public boolean isAllTaskDone(Map<String, Future<?>> bundleNameFutureMap) {
+ boolean anyNotDone = bundleNameFutureMap.values().stream().anyMatch((f) -> !f.isDone());
+ return !anyNotDone;
+ }
+
+ /**
+ * Cancel BunldeTasks which are not finished
+ * @param bundleNameFutureMap with bundler name and BundleTask Future object
+ */
+ public void cancelUnfinished(Map<String, Future<?>> bundleNameFutureMap) {
+ bundleNameFutureMap.values().stream().filter((f) -> !f.isDone()).forEach((f) -> f.cancel(true));
+ }
+
+ /**
+ * Get number of failed BundleTasks
+ * @param bundleNameFurtureMap with bundler name and BundleTask Future object
+ * @return number(long) of the failed BundleTasks
+ */
+ public long getFailedMetrics(Map<String, Future<?>> bundleNameFurtureMap) {
+ return bundleNameFurtureMap.values().stream().map((f) -> {
+ try {
+ return f.get();
+ } catch (Exception e) {
+ // should not get here
+ throw new RuntimeException(e);
+ }
+ }).filter((b) -> ((BundleTask)b).failException != null).count();
+ }
+
+ /**
+ * Gets the list of Appc-bundles to be stopped/started
+ *
+ * @return Map of bundle symbolic name and bundle instance
+ */
+ Map<String, Bundle> getAppcLcmBundles() {
+ logDebug("In getAppcLcmBundles");
+
+ String[] bundlesToStop = readPropsFromPropListName(PROP_BUNDLE_TO_STOP);
+ String[] regExBundleNotStop = readPropsFromPropListName(PROP_BUNDLES_TO_NOT_STOP);
+
+ BundleFilter bundleList = new BundleFilter(bundlesToStop, regExBundleNotStop, getBundleList());
+
+ logger.info(String.format("(%d) APPC bundles to Stop/Start: %s.", bundleList.getBundlesToStop().size(),
+ bundleList.getBundlesToStop().toString()));
+
+ logger.debug(String.format("(%d) APPC bundles that won't be Stopped/Started: %s.",
+ bundleList.getBundlesToNotStop().size(), bundleList.getBundlesToNotStop().toString()));
+
+ return bundleList.getBundlesToStop();
+ }
+
+ /**
+ * Gets a list of all user desired bundles that should be stopped/Started as part of
+ * OAM Stop and Start API
+ *
+ * @param propListKey String of the properties list property name
+ * @return properties values of the related
+ */
+ String[] readPropsFromPropListName(String propListKey) {
+ // get properties list by properties list name
+ String[] propNames = configurationHelper.readProperty(propListKey);
+ // go through each property to get the property values
+ String[] propValue = ArrayUtils.EMPTY_STRING_ARRAY;
+ if (propNames != null) {
+ for (String aPropName : propNames) {
+ propValue = ArrayUtils.addAll(propValue, configurationHelper.readProperty(aPropName));
+ }
+ }
+ return propValue;
+ }
+
+ /**
+ * Get all bundle list of APP-C
+ * @return Array of Bundle
+ */
+ Bundle[] getBundleList() {
+ BundleContext myBundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+ if (myBundleContext != null) {
+ return myBundleContext.getBundles();
+ }
+ return null;
+ }
+
+ /**
+ * Genral debug log when debug logging level is enabled.
+ * @param message of the log message format
+ * @param args of the objects listed in the message format
+ */
+ private void logDebug(String message, Object... args) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format(message, args));
+ }
+ }
+
+ /**
+ * Runnable to execute bundle operations: start or stop
+ */
+ class BundleTask implements Callable<BundleTask> {
+ Exception failException;
+
+ private AppcOam.RPC rpc;
+ private Bundle bundle;
+ private String bundleName;
+ private String actionName;
+
+ BundleTask(AppcOam.RPC rpcIn, Bundle bundleIn) {
+ rpc = rpcIn;
+ actionName = rpc.getAppcOperation().toString();
+ bundle = bundleIn;
+ bundleName = bundle.getSymbolicName();
+ }
+
+ @Override
+ public BundleTask call() throws Exception {
+ try {
+ long bundleOperStartTime = System.currentTimeMillis();
+ logDebug(String.format("OAM %s bundle %s ===>", actionName, bundleName));
+ switch (rpc) {
+ case start:
+ bundle.start();
+ break;
+ case stop:
+ bundle.stop();
+ break;
+ default:
+ // should do nothing
+ }
+ logDebug(String.format("OAM %s bundle %s completed <=== elasped %d",
+ actionName, bundleName, getElaspeTimeMs(bundleOperStartTime)));
+ } catch (BundleException e) {
+ logger.error(String.format("Exception encountered when OAM %s bundle %s ",
+ actionName, bundleName), e);
+ failException = e;
+ }
+ return this;
+ }
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/ConfigurationHelper.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/ConfigurationHelper.java
new file mode 100644
index 000000000..c465b9b10
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/ConfigurationHelper.java
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.apache.commons.lang3.ArrayUtils;
+import org.openecomp.appc.Constants;
+import org.openecomp.appc.configuration.Configuration;
+import org.openecomp.appc.configuration.ConfigurationFactory;
+
+/**
+ * Utility class provides general configuration helps
+ */
+public class ConfigurationHelper {
+ final static String PROP_KEY_APPC_NAME = Constants.PROPERTY_APPLICATION_NAME;
+ final static String PROP_KEY_METRIC_STATE = "metric.enabled";
+
+ private final EELFLogger logger;
+ private Configuration configuration = ConfigurationFactory.getConfiguration();
+
+ public ConfigurationHelper(EELFLogger eelfLogger) {
+ logger = eelfLogger;
+ }
+
+ public String getAppcName() {
+ return configuration.getProperty(PROP_KEY_APPC_NAME);
+ }
+
+ public boolean isMetricEnabled() {
+ return configuration.getBooleanProperty(PROP_KEY_METRIC_STATE, false);
+ }
+
+ public Configuration getConfig() {
+ return configuration;
+ }
+
+ /**
+ * Read property value of a specified proeprty key
+ *
+ * @param propertyKey string of the property key
+ * @return String[] of the property values associated with the propertyKey
+ */
+ String[] readProperty(String propertyKey) {
+ String propertyValue = configuration.getProperty(propertyKey);
+ if (propertyValue == null) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format("Property[%s] has value (%s).", propertyKey, propertyValue));
+ }
+
+ if (propertyValue.contains(",")) {
+ return propertyValue.split("\\s*,\\s*");
+ }
+ return new String[]{propertyValue};
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/OperationHelper.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/OperationHelper.java
new file mode 100644
index 000000000..0b20104f4
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/OperationHelper.java
@@ -0,0 +1,205 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.MaintenanceModeInput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.RestartInput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StartInput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.StopInput;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.common.header.CommonHeader;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.common.header.common.header.Flags;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.Status;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.exceptions.InvalidInputException;
+import org.openecomp.appc.exceptions.InvalidStateException;
+import org.openecomp.appc.lifecyclemanager.LifecycleManager;
+import org.openecomp.appc.lifecyclemanager.objects.LifecycleException;
+import org.openecomp.appc.lifecyclemanager.objects.NoTransitionDefinedException;
+import org.openecomp.appc.oam.AppcOam;
+import org.openecomp.appc.oam.messageadapter.MessageAdapter;
+import org.openecomp.appc.oam.messageadapter.OAMContext;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamMetaDataReader;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Utility class provides general operational helps.
+ */
+@SuppressWarnings("unchecked")
+public class OperationHelper {
+ final String MISSING_COMMON_HEADER_MESSAGE = "Missing common header";
+ final String MISSING_FIELD_MESSAGE = "Common header must have both originatorId and requestId";
+ final String NOT_SUPPORT_FLAG = "Flags is not supported by this operation";
+ final String NO_SERVICE_REF_FORMAT = "Using the BundleContext failed to get service reference for %s";
+
+ private final EELFLogger logger = EELFManager.getInstance().getLogger(OperationHelper.class);
+ private LifecycleManager lifecycleMgr;
+ private MessageAdapter messageAdapter;
+
+ public OperationHelper() {
+ // do nothing
+ }
+
+ /**
+ * This method is used to validate OAM REST API input due to the following ODL bugs results no validation : </tt>
+ * <p> - <a href="https://bugs.opendaylight.org/show_bug.cgi?id=8088">
+ * Bug 8088 - Mandatory attributes in RPC input are not honoured</a>
+ * <p> - <a href="https://bugs.opendaylight.org/show_bug.cgi?id=5830">
+ * Bug 5830 - Mandatory leaf enforcement is not correct with presence container</a>
+ *
+ * @param inputObject object from the OAM REST API input object
+ * @throws InvalidInputException is thrown when the commonHeader is invalid
+ */
+ public void isInputValid(final Object inputObject) throws InvalidInputException {
+ CommonHeader commonHeader = getCommonHeader(inputObject);
+ if (commonHeader == null) {
+ throw new InvalidInputException(MISSING_COMMON_HEADER_MESSAGE);
+ }
+
+ if (commonHeader.getOriginatorId() == null
+ || commonHeader.getRequestId() == null) {
+ throw new InvalidInputException(MISSING_FIELD_MESSAGE);
+ }
+
+ // check Flags
+ if (inputObject instanceof MaintenanceModeInput
+ && commonHeader.getFlags() != null) {
+ throw new InvalidInputException(NOT_SUPPORT_FLAG);
+ }
+ }
+
+ /**
+ * Get commonHead of the inputObject (expecting the inputObject of OAM REST API)
+ * @param inputObject the OAM REST API input object
+ * @return CommonHeader of the inputObject. If the inputObject is not a OAM REST API input, null is returned.
+ */
+ public CommonHeader getCommonHeader(final Object inputObject) {
+ if (inputObject instanceof StartInput) {
+ return ((StartInput)inputObject).getCommonHeader();
+ }
+ if (inputObject instanceof StopInput) {
+ return ((StopInput)inputObject).getCommonHeader();
+ }
+ if (inputObject instanceof MaintenanceModeInput) {
+ return ((MaintenanceModeInput)inputObject).getCommonHeader();
+ }
+ if (inputObject instanceof RestartInput) {
+ return ((RestartInput)inputObject).getCommonHeader();
+ }
+ return null;
+ }
+
+ public Integer getParamRequestTimeout(final Object inputObject) {
+ if (inputObject instanceof MaintenanceModeInput) {
+ // maintanence mode, we do not support request timeout
+ return 0;
+ }
+
+ CommonHeader commonHeader = getCommonHeader(inputObject);
+ if (commonHeader == null) {
+ return 0;
+ }
+
+ Flags inputFlags = commonHeader.getFlags();
+ if (inputFlags == null) {
+ return null;
+ }
+ return inputFlags.getRequestTimeout();
+ }
+ /**
+ * Get service instance using bundle context.
+ *
+ * @param _class of the expected service instance
+ * @param <T> of the expected service instance
+ * @return service instance of the expected
+ * @throws APPCException when cannot find service reference or service isntance
+ */
+ public <T> T getService(Class<T> _class) throws APPCException {
+ BundleContext bctx = FrameworkUtil.getBundle(_class).getBundleContext();
+ if (bctx != null) {
+ ServiceReference sref = bctx.getServiceReference(_class.getName());
+ if (sref != null) {
+ if (logger.isTraceEnabled()) {
+ logger.debug("Using the BundleContext got the service reference for " + _class.getName());
+ }
+ return (T) bctx.getService(sref);
+ }
+ }
+
+ throw new APPCException(String.format(NO_SERVICE_REF_FORMAT, _class.getName()));
+ }
+
+ /**
+ * Get next valid state from life cycle manager.
+ *
+ * @param operation of the AppcOperation for the state changes
+ * @param currentState of AppcOamStates
+ * @return next AppcOamStates based on the currentState and operation
+ * @throws APPCException If life cycle manager instance cannot be retrieved
+ * @throws InvalidStateException when the operation is not supported on the currentState
+ */
+ public AppcOamStates getNextState(AppcOamMetaDataReader.AppcOperation operation, AppcOamStates currentState)
+ throws APPCException, InvalidStateException {
+ if (lifecycleMgr == null) {
+ lifecycleMgr = getService(LifecycleManager.class);
+ }
+
+ try {
+ String nextState = lifecycleMgr.getNextState("APPC", currentState.name(), operation.toString());
+ if (nextState != null) {
+ return AppcOamStates.valueOf(nextState);
+ }
+ } catch (LifecycleException |NoTransitionDefinedException ex) {
+ logger.error("Invalid next state based on the current state and attempted Operation " + ex.getMessage());
+ }
+
+ throw new InvalidStateException(String.format(AppcOam.INVALID_STATE_MESSAGE_FORMAT, operation, "APPC", currentState));
+ }
+
+ /**
+ * Post notification through MessageAdapter.
+ *
+ * @param rpc of REST API RPC
+ * @param commonHeader of REST API request common header
+ * @param status of the to be post message
+ */
+ public void sendNotificationMessage(AppcOam.RPC rpc, CommonHeader commonHeader, Status status) {
+ if (messageAdapter == null) {
+ messageAdapter = new MessageAdapter();
+ messageAdapter.init();
+
+ }
+
+ OAMContext oamContext = new OAMContext();
+ oamContext.setRpcName(rpc);
+ oamContext.setCommonHeader(commonHeader);
+ oamContext.setStatus(status);
+ messageAdapter.post(oamContext);
+ }
+}
diff --git a/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/StateHelper.java b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/StateHelper.java
new file mode 100644
index 000000000..a9ccc26d0
--- /dev/null
+++ b/appc-oam/appc-oam-bundle/src/main/java/org/openecomp/appc/oam/util/StateHelper.java
@@ -0,0 +1,144 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.oam.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.AppcState;
+import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
+import org.osgi.framework.Bundle;
+
+import java.util.Map;
+
+/*
+ * Utility class provides general state helps
+ */
+public class StateHelper {
+ /** logger inherited from AppcOam */
+ private final EELFLogger logger;
+ private ConfigurationHelper configurationHelper;
+ /** APP-C OAM current state in AppcOamStates value */
+ private volatile AppcOamStates appcOamCurrentState;
+
+ /**
+ * Constructor
+ *
+ * @param eelfLogger of the logger
+ */
+ public StateHelper(EELFLogger eelfLogger, ConfigurationHelper cHelper) {
+ logger = eelfLogger;
+ configurationHelper = cHelper;
+ appcOamCurrentState = AppcOamStates.Unknown;
+ }
+
+ /**
+ * Set the passed in state to the class <b>appOamCurrentState</b>.
+ *
+ * @param appcOamStates of the new state
+ */
+ public void setState(AppcOamStates appcOamStates) {
+ appcOamCurrentState = appcOamStates;
+ }
+
+ /**
+ * Get the state
+ * @return the class <b>appOamCurrentState</b>
+ */
+ public AppcOamStates getState() {
+ return appcOamCurrentState;
+ }
+
+ /**
+ * Validate if the passed in state is the same as the class <b>appOamCurrentState</b>.
+ *
+ * @param appcOamStates of the to be compared state
+ * @return true if they are the same, otherwise false
+ */
+ boolean isSameState(AppcOamStates appcOamStates) {
+ return appcOamCurrentState == appcOamStates;
+ }
+
+ /**
+ * Get APP-C OAM current state
+ *
+ * <p>When appcOamCurrentState is null or unknown, reset it with APPC LCM bundle state.
+ *
+ * @return AppcOamStates of the current APP-C OAM state
+ */
+ public AppcOamStates getCurrentOamState() {
+ if (appcOamCurrentState == null || appcOamCurrentState.equals(AppcOamStates.Unknown)) {
+ appcOamCurrentState = getBundlesState();
+ }
+ return appcOamCurrentState;
+ }
+
+ /**
+ * Use getCurrentOamState to get current OAM AppcOamStates and then convert to AppcState of Yang.
+ *
+ * @return AppcState of current OAM state
+ */
+ public AppcState getCurrentOamYangState() {
+ try {
+ AppcOamStates appcOamStates = getCurrentOamState();
+ return AppcState.valueOf(appcOamStates.name());
+ } catch (Exception ex) {
+ logger.error(String.format("Unable to determine the current APP-C OAM state due to %s.", ex.getMessage()));
+ }
+ return AppcState.Unknown;
+ }
+
+ /**
+ * Get APPC state from the state of the set of APPC LCM bundles.
+ * <p>The state of each bundle will be checked and the lowest state will be uses as the returning AppcOamStates.
+ * <p>The bundle state order are defined in OSGI bundle (@see org.osgi.framework.Bundle) class
+ * as the int value assigned to each state as the following: <br>
+ * - UNINSTALLED (1) <br>
+ * - INSTALLED (2) <br>
+ * - RESOLVED (4) <br>
+ * - STARTING (8) <br>
+ * - STOPPING (16) <br>
+ * - ACTIVE (32) <br>
+ *
+ * @return AppcOamStates
+ */
+ public AppcOamStates getBundlesState() {
+ BundleHelper bundleHelper = new BundleHelper(logger, configurationHelper, this);
+ Map<String, Bundle> lcmBundleMap = bundleHelper.getAppcLcmBundles();
+ if (lcmBundleMap == null || lcmBundleMap.isEmpty()) {
+ return AppcOamStates.Unknown;
+ }
+
+ // As we are picking up the lowest bundle state as general APP-C state, we will start with ACTIVE
+ int currentState = Bundle.ACTIVE;
+ for (Bundle bundle : lcmBundleMap.values()) {
+ int bundleState = bundle.getState();
+ logger.trace(String.format("getBundlesState: [%s] has state (%d)", bundle.getSymbolicName(), bundleState));
+ if (bundleState < currentState) {
+ currentState = bundleState;
+ }
+ }
+ return AppcOamStates.getOamStateFromBundleState(currentState);
+ }
+
+}
diff --git a/appc-oam/appc-oam-model/src/main/yang/appc-oam.yang b/appc-oam/appc-oam-model/src/main/yang/appc-oam.yang
index d84d8ce79..03675c8f2 100644
--- a/appc-oam/appc-oam-model/src/main/yang/appc-oam.yang
+++ b/appc-oam/appc-oam-model/src/main/yang/appc-oam.yang
@@ -77,6 +77,17 @@ module appc-oam {
mandatory true;
}
+ container flags {
+ leaf request-timeout {
+ description "The allowed time in seconds to perform the request. If the request cannot
+ be completed in this amount of time, the request is aborted with OAM state set
+ to Error. If set to zero, no timeout exists and the request will be handled
+ continue until operation completes or fails. If omitted, the default value of
+ 20 is used.";
+ type uint16;
+ mandatory false;
+ }
+ }
}
}
@@ -103,6 +114,23 @@ module appc-oam {
}
}
+ typedef appc-state {
+ type enumeration {
+ enum "Error";
+ enum "Unknown";
+ enum "Not_Instantiated"; // Equivalent to Bundle's UNINSTALL
+ enum "Instantiated"; // Equivalent to Bundle's INSTALL
+ enum "Starting";
+ enum "Started";
+ enum "EnteringMaintenanceMode";
+ enum "MaintenanceMode";
+ enum "Stopping";
+ enum "Stopped";
+ enum "Restarting";
+ }
+ description "Refers to the various states an APP-C instance can be in";
+ }
+
rpc get-metrics {
description "An operation to get list of registered Metrics in APP-C";
output {
@@ -135,10 +163,10 @@ module appc-oam {
}
}
- rpc stop {
+ rpc maintenance-mode {
description "An operation that disables appc-provider-lcm so that it no longer accepts LCM request. This
operation has no impact on queued and currently executing LCM request. A notification will be
- sent out indicating the APP-C is idle once all LCM request have completed execution. ";
+ sent out indicating the APP-C is idle once all LCM request have completed execution.";
input {
uses common-header;
}
@@ -149,13 +177,46 @@ module appc-oam {
}
rpc start {
- description "An operation that enables appc-provider-lcm so that it can begin to accepts LCM request. ";
+ description "An operation that enables appc-provider-lcm so that it can begin to accepts LCM request. This
+ includes starting any appc bundles which are stopped.";
input {
- uses common-header;
+ uses common-header;
}
output {
uses common-header;
uses status;
}
}
+
+ rpc get-appc-state {
+ description "Returns the current state of the running APPC LCM instance";
+ output {
+ leaf state {
+ type appc-state;
+ }
+ }
+ }
+
+ rpc stop {
+ description "Force stops the APPC bundles that accept LCM requests";
+ // Note: OAM feature bundles and it's dependencies (Appc-common and LifeCycle Manager) would continue to run
+ input {
+ uses common-header;
+ }
+ output {
+ uses common-header;
+ uses status;
+ }
+ }
+
+ rpc restart {
+ description "An operation that restarts APPC by invoking the stop rpc followed by the start rpc.";
+ input {
+ uses common-header;
+ }
+ output {
+ uses common-header;
+ uses status;
+ }
+ }
}