summaryrefslogtreecommitdiffstats
path: root/feature-lifecycle/src/main
diff options
context:
space:
mode:
authorJorge Hernandez <jorge.hernandez-herrero@att.com>2019-03-28 01:12:10 -0500
committerjhh <jorge.hernandez-herrero@att.com>2019-04-02 20:48:41 -0500
commit964b127fc75e202d3c661454dbea58acf2b234c6 (patch)
treec2991183110e1ba8ec0905350eb2256d5f3c1cec /feature-lifecycle/src/main
parent92cb38f9137d80328445d7b22cb51716783e3aea (diff)
Initial lifecycle state machine.
Basic state machine and initial functionality to transition to the Active state via Engine commands and StateUpdate messages. Change-Id: I8212bd264dbbea446d4e682918f9360e3984887f Issue-ID: POLICY-1608 Signed-off-by: Jorge Hernandez <jorge.hernandez-herrero@att.com> Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
Diffstat (limited to 'feature-lifecycle/src/main')
-rw-r--r--feature-lifecycle/src/main/feature/config/feature-lifecycle.properties34
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java69
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java325
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleState.java78
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java67
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateDefault.java88
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java63
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateSafe.java41
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminated.java86
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTest.java44
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupported.java78
-rw-r--r--feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureAPI1
-rw-r--r--feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI1
-rw-r--r--feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI1
14 files changed, 976 insertions, 0 deletions
diff --git a/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties b/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties
new file mode 100644
index 00000000..2cdc2abf
--- /dev/null
+++ b/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties
@@ -0,0 +1,34 @@
+# ============LICENSE_START=======================================================
+# ONAP
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+dmaap.source.topics=POLICY-PDP-PAP
+dmaap.sink.topics=POLICY-PDP-PAP
+
+dmaap.source.topics.POLICY-PDP-PAP.servers=${env:DMAAP_SERVERS}
+dmaap.source.topics.POLICY-PDP-PAP.effectiveTopic=${env:POLICY_PDP_PAP_TOPIC}
+dmaap.source.topics.POLICY-PDP-PAP.apiKey=${env:POLICY_PDP_PAP_API_KEY}
+dmaap.source.topics.POLICY-PDP-PAP.apiSecret=${env:POLICY_PDP_PAP_API_SECRET}
+dmaap.source.topics.POLICY-PDP-PAP.managed=false
+dmaap.source.topics.POLICY-PDP-PAP.https=true
+
+dmaap.sink.topics.POLICY-PDP-PAP.servers=${env:DMAAP_SERVERS}
+dmaap.sink.topics.POLICY-PDP-PAP.effectiveTopic=${env:POLICY_PDP_PAP_TOPIC}
+dmaap.sink.topics.POLICY-PDP-PAP.apiKey=${env:POLICY_PDP_PAP_API_KEY}
+dmaap.sink.topics.POLICY-PDP-PAP.apiSecret=${env:POLICY_PDP_PAP_API_SECRET}
+dmaap.sink.topics.POLICY-PDP-PAP.managed=false
+dmaap.sink.topics.POLICY-PDP-PAP.https=true
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java
new file mode 100644
index 00000000..5e1ddaea
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import org.onap.policy.drools.features.DroolsControllerFeatureAPI;
+import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
+import org.onap.policy.drools.features.PolicyEngineFeatureAPI;
+import org.onap.policy.drools.system.PolicyEngine;
+
+/**
+ * This class hooks the Lifecycle State Machine to the PDP-D.
+ */
+public class LifecycleFeature
+ implements PolicyEngineFeatureAPI, DroolsControllerFeatureAPI, PolicyControllerFeatureAPI {
+ /**
+ * Lifecycle FSM.
+ */
+ protected static final LifecycleFsm fsm = new LifecycleFsm();
+
+ @Override
+ public int getSequenceNumber() {
+ return 10;
+ }
+
+ /**
+ * The 'afterStart' hook on the Policy Engine tell us when the engine is functional.
+ */
+ @Override
+ public boolean afterStart(PolicyEngine engine) {
+ fsm.start();
+ return false;
+ }
+
+ /**
+ * The 'afterStop' hook on the Policy Engine tell us when the engine is stopping.
+ */
+ @Override
+ public boolean afterStop(PolicyEngine engine) {
+ fsm.stop();
+ return false;
+ }
+
+ /**
+ * The 'beforeShutdown' hook on the Policy Engine tell us when the engine is going away.
+ */
+ @Override
+ public boolean beforeShutdown(PolicyEngine engine) {
+ fsm.shutdown();
+ return false;
+ }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java
new file mode 100644
index 00000000..61f6de99
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java
@@ -0,0 +1,325 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.UUID;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.policy.common.capabilities.Startable;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.event.comm.TopicSource;
+import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient;
+import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher;
+import org.onap.policy.common.endpoints.listeners.ScoListener;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
+import org.onap.policy.common.utils.coder.StandardCoderObject;
+import org.onap.policy.common.utils.network.NetworkUtil;
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.persistence.SystemPersistence;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpStatus;
+import org.onap.policy.models.pdp.concepts.PolicyTypeIdent;
+import org.onap.policy.models.pdp.enums.PdpHealthStatus;
+import org.onap.policy.models.pdp.enums.PdpMessageType;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle FSM.
+ */
+public class LifecycleFsm implements Startable {
+
+ protected static final String CONFIGURATION_PROPERTIES_NAME = "feature-lifecycle";
+ protected static final String POLICY_TYPE_VERSION = "1.0.0";
+ protected static final long DEFAULT_STATUS_TIMER_SECONDS = 60L;
+ protected static final String PDP_MESSAGE_NAME = "messageName";
+
+ private static final Logger logger = LoggerFactory.getLogger(LifecycleFsm.class);
+
+ protected final Properties properties;
+
+ protected TopicSource source;
+ protected TopicSinkClient client;
+
+ protected volatile LifecycleState state = new LifecycleStateTerminated(this);
+
+ @GsonJsonIgnore
+ protected ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1);
+
+ @GsonJsonIgnore
+ protected ScheduledFuture<?> statusTask;
+
+ @GsonJsonIgnore
+ protected MessageTypeDispatcher sourceDispatcher = new MessageTypeDispatcher(new String[]{PDP_MESSAGE_NAME});
+
+ @GsonJsonIgnore
+ protected MessageNameDispatcher nameDispatcher = new MessageNameDispatcher(PdpStateChange.class, this);
+
+ @Getter
+ @Setter
+ protected long statusTimerSeconds = DEFAULT_STATUS_TIMER_SECONDS;
+
+ @Getter
+ protected String pdpGroup;
+
+ @Getter
+ protected String pdpSubgroup;
+
+ /**
+ * Constructor.
+ */
+ public LifecycleFsm() {
+ this.properties = SystemPersistence.manager.getProperties(CONFIGURATION_PROPERTIES_NAME);
+
+ scheduler.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
+ scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
+ scheduler.setRemoveOnCancelPolicy(true);
+ }
+
+ @Override
+ public boolean isAlive() {
+ return client != null && client.getSink().isAlive();
+ }
+
+ /**
+ * Current state.
+ */
+ public PdpState state() {
+ return state.state();
+ }
+
+ /* ** FSM events - entry points of events into the FSM ** */
+
+ @Override
+ public synchronized boolean start() {
+ logger.info("lifecycle event: start");
+ return state.start();
+ }
+
+ @Override
+ public synchronized boolean stop() {
+ logger.info("lifecycle event: stop");
+ return state.stop();
+ }
+
+ @Override
+ public synchronized void shutdown() {
+ logger.info("lifecycle event: shutdown");
+ state.shutdown();
+ }
+
+ /**
+ * Status reporting event.
+ * @return true if successful
+ */
+ public synchronized boolean status() {
+ logger.info("lifecycle event: status");
+ return state.status();
+ }
+
+ public synchronized void stateChange(PdpStateChange stateChange) {
+ logger.info("lifecycle event: state-change");
+ state.stateChange(stateChange);
+ }
+
+ /* ** FSM State Actions ** */
+
+ protected boolean startAction() {
+ if (isAlive()) {
+ return true;
+ }
+
+ return startIo() && startTimers();
+ }
+
+ protected boolean stopAction() {
+ if (!isAlive()) {
+ return true;
+ }
+
+ boolean successTimers = stopTimers();
+ boolean successIo = stopIo();
+ return successTimers && successIo;
+ }
+
+ protected void shutdownAction() {
+ shutdownIo();
+ shutdownTimers();
+ }
+
+ protected boolean statusAction(PdpState state) {
+ if (!isAlive()) {
+ return false;
+ }
+
+ return client.send(statusPayload(state));
+ }
+
+ protected void setGroupAction(String group, String subgroup) {
+ this.pdpGroup = group;
+ this.pdpSubgroup = subgroup;
+ }
+
+ protected void transitionToAction(@NonNull LifecycleState newState) {
+ state = newState;
+ }
+
+ /* ** Action Helpers ** */
+
+ private boolean startIo() {
+ return source() && sink();
+ }
+
+ private boolean startTimers() {
+ statusTask =
+ this.scheduler.scheduleAtFixedRate(() -> status(), 0, statusTimerSeconds, TimeUnit.SECONDS);
+ return !statusTask.isCancelled() && !statusTask.isDone();
+ }
+
+ private boolean stopIo() {
+ source.unregister(sourceDispatcher);
+ boolean successSource = source.stop();
+ boolean successSink = client.getSink().stop();
+ return successSource && successSink;
+ }
+
+ private boolean stopTimers() {
+ boolean success = true;
+ if (statusTask != null) {
+ success = statusTask.cancel(false);
+ }
+
+ return success;
+ }
+
+ private void shutdownIo() {
+ client.getSink().shutdown();
+ source.shutdown();
+ }
+
+ private void shutdownTimers() {
+ scheduler.shutdownNow();
+ }
+
+ private PdpStatus statusPayload(PdpState state) {
+ PdpStatus status = new PdpStatus();
+ status.setRequestId(UUID.randomUUID().toString());
+ status.setTimestampMs(System.currentTimeMillis());
+ status.setInstance(NetworkUtil.getHostname());
+ status.setState(state);
+ status.setHealthy(isAlive() ? PdpHealthStatus.HEALTHY : PdpHealthStatus.NOT_HEALTHY);
+ status.setPdpType("drools"); // TODO: enum ?
+ return status;
+ }
+
+ private boolean source() {
+ List<TopicSource> sources = TopicEndpoint.manager.addTopicSources(properties);
+ if (sources.isEmpty()) {
+ return false;
+ }
+
+ if (sources.size() != 1) {
+ logger.warn("Lifecycle Manager: unexpected: more than one source configured ({})", sources.size());
+ }
+
+ this.source = sources.get(0);
+ this.source.register(this.sourceDispatcher);
+ this.sourceDispatcher.register(PdpMessageType.PDP_STATE_CHANGE.name(), nameDispatcher);
+ return source.start();
+ }
+
+ private boolean sink() {
+ List<TopicSink> sinks = TopicEndpoint.manager.addTopicSinks(properties);
+ if (sinks.isEmpty()) {
+ logger.error("Lifecycle Manager sinks have not been configured");
+ return false;
+ }
+
+ if (sinks.size() != 1) {
+ logger.warn("Lifecycle Manager: unexpected: more than one sink configured ({})", sinks.size());
+ }
+
+ this.client = new TopicSinkClient(sinks.get(0));
+ return this.client.getSink().start();
+ }
+
+ private List<PolicyTypeIdent> getCapabilities() {
+ List<PolicyTypeIdent> capabilities = new ArrayList<>();
+ for (DroolsController dc : DroolsController.factory.inventory()) {
+ if (!dc.isBrained()) {
+ continue;
+ }
+
+ for (String domain : dc.getBaseDomainNames()) {
+ // HACK: until legacy controllers are removed
+ if (StringUtils.countMatches(domain, ".") > 1) {
+ capabilities.add(new PolicyTypeIdent(domain, POLICY_TYPE_VERSION));
+ } else {
+ logger.info("legacy controller {} with domain {}", dc.getCanonicalSessionNames(), domain);
+ }
+ }
+ }
+ return capabilities;
+ }
+
+
+ /* **** IO listeners ***** */
+
+ /**
+ * PDP State Change Message Listener.
+ */
+ public static class MessageNameDispatcher extends ScoListener<PdpStateChange> {
+
+ protected final LifecycleFsm fsm;
+
+ /**
+ * Constructor.
+ */
+ public MessageNameDispatcher(Class<PdpStateChange> clazz, LifecycleFsm fsm) {
+ super(clazz);
+ this.fsm = fsm;
+ }
+
+ @Override
+ public void onTopicEvent(CommInfrastructure commInfrastructure, String topic,
+ StandardCoderObject standardCoderObject, PdpStateChange pdpStateChange) {
+
+ if (pdpStateChange == null) {
+ logger.warn("pdp-state-chage null from {}:{}", commInfrastructure, topic);
+ return;
+ }
+
+ fsm.stateChange(pdpStateChange);
+ }
+ }
+
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleState.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleState.java
new file mode 100644
index 00000000..e07df151
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleState.java
@@ -0,0 +1,78 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import lombok.NonNull;
+import org.onap.policy.common.capabilities.Startable;
+import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle State.
+ */
+public abstract class LifecycleState implements Startable {
+
+ private static final Logger logger = LoggerFactory.getLogger(LifecycleState.class);
+
+ @GsonJsonIgnore
+ protected LifecycleFsm fsm;
+
+ /**
+ * Constructor.
+ * @param manager Lifecycle Manager.
+ */
+ public LifecycleState(@NonNull LifecycleFsm manager) {
+ this.fsm = manager;
+ }
+
+ /**
+ * change state.
+ * @param newState new state
+ */
+ public abstract boolean transitionToState(@NonNull LifecycleState newState);
+
+ /**
+ * current state.
+ * @return state
+ */
+ public abstract PdpState state();
+
+ /**
+ * status event.
+ */
+ public abstract boolean status();
+
+ /**
+ * update event.
+ * @param update message
+ */
+ public abstract void update(@NonNull PdpUpdate update);
+
+ /**
+ * state change event .
+ * @param change message
+ */
+ public abstract void stateChange(@NonNull PdpStateChange change);
+} \ No newline at end of file
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java
new file mode 100644
index 00000000..d5be822b
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java
@@ -0,0 +1,67 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle Active State.
+ */
+@ToString
+public class LifecycleStateActive extends LifecycleStateDefault {
+
+ private static final Logger logger = LoggerFactory.getLogger(LifecycleStateActive.class);
+
+ /**
+ * Constructor.
+ * @param manager fsm
+ */
+ public LifecycleStateActive(LifecycleFsm manager) {
+ super(manager);
+ }
+
+ @Override
+ public PdpState state() {
+ return PdpState.ACTIVE;
+ }
+
+ @Override
+ public void stateChange(PdpStateChange change) {
+ synchronized (fsm) {
+ if (change.getState() == PdpState.ACTIVE) {
+ fsm.setGroupAction(change.getPdpGroup(), change.getPdpSubgroup());
+ return;
+ }
+
+ if (change.getState() != PdpState.PASSIVE) {
+ logger.warn("{}: state-change: {}", this, change);
+ return;
+ }
+
+ fsm.setGroupAction(change.getPdpGroup(), change.getPdpSubgroup());
+ fsm.transitionToAction(new LifecycleStatePassive(fsm));
+ }
+ }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateDefault.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateDefault.java
new file mode 100644
index 00000000..18e40012
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateDefault.java
@@ -0,0 +1,88 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import lombok.NonNull;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Support class for default functionality for operational states.
+ */
+public abstract class LifecycleStateDefault extends LifecycleStateUnsupported {
+
+ private static final Logger logger = LoggerFactory.getLogger(LifecycleState.class);
+
+ public LifecycleStateDefault(LifecycleFsm manager) {
+ super(manager);
+ }
+
+
+ @Override
+ public boolean transitionToState(@NonNull LifecycleState newState) {
+ logger.info("{}: state-change from {} to {}", this, state(), newState.state());
+
+ synchronized (fsm) {
+ if (state() == newState.state()) {
+ return false;
+ }
+
+ fsm.transitionToAction(newState);
+ return true;
+ }
+ }
+
+ @Override
+ public boolean start() {
+ logger.warn("{}: start", this);
+ return false;
+ }
+
+ @Override
+ public boolean stop() {
+ synchronized (fsm) {
+ boolean success = fsm.statusAction(PdpState.TERMINATED);
+ success = fsm.stopAction() && success;
+ return transitionToState(new LifecycleStateTerminated(fsm)) && success;
+ }
+ }
+
+ @Override
+ public void shutdown() {
+ synchronized (fsm) {
+ stop();
+ fsm.shutdownAction();
+ }
+ }
+
+ @Override
+ public boolean isAlive() {
+ return true;
+ }
+
+ @Override
+ public boolean status() {
+ synchronized (fsm) {
+ return fsm.statusAction(state());
+ }
+ }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java
new file mode 100644
index 00000000..dc184e87
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle Passive State.
+ */
+
+@ToString
+public class LifecycleStatePassive extends LifecycleStateDefault {
+
+ private static final Logger logger = LoggerFactory.getLogger(LifecycleStatePassive.class);
+
+ /**
+ * Constructor.
+ * @param manager fsm
+ */
+ public LifecycleStatePassive(LifecycleFsm manager) {
+ super(manager);
+ }
+
+ @Override
+ public PdpState state() {
+ return PdpState.PASSIVE;
+ }
+
+ @Override
+ public void stateChange(PdpStateChange change) {
+ synchronized (fsm) {
+ if (change.getState() != PdpState.ACTIVE) {
+ logger.warn("{}: state-change: {}", this, change);
+ return;
+ }
+
+ fsm.setGroupAction(change.getPdpGroup(), change.getPdpSubgroup());
+ fsm.transitionToAction(new LifecycleStateActive(fsm));
+ }
+ }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateSafe.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateSafe.java
new file mode 100644
index 00000000..e0ea2b5e
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateSafe.java
@@ -0,0 +1,41 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.enums.PdpState;
+
+/**
+ * Lifecycle Safe State.
+ */
+
+@ToString
+public class LifecycleStateSafe extends LifecycleStateUnsupported {
+
+ public LifecycleStateSafe(LifecycleFsm manager) {
+ super(manager);
+ }
+
+ @Override
+ public PdpState state() {
+ return PdpState.SAFE;
+ }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminated.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminated.java
new file mode 100644
index 00000000..7455349c
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminated.java
@@ -0,0 +1,86 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lifecycle Terminated State.
+ */
+
+@ToString
+public class LifecycleStateTerminated extends LifecycleStateDefault {
+
+ private static final Logger logger = LoggerFactory.getLogger(LifecycleStateTerminated.class);
+
+ protected LifecycleStateTerminated(LifecycleFsm manager) {
+ super(manager);
+ }
+
+ @Override
+ public PdpState state() {
+ return PdpState.TERMINATED;
+ }
+
+ @Override
+ public boolean start() {
+ synchronized (fsm) {
+ boolean success = fsm.startAction();
+ if (success) {
+ return transitionToState(new LifecycleStatePassive(fsm));
+ }
+
+ return false;
+ }
+ }
+
+ @Override
+ public boolean stop() {
+ logger.warn("{}: stop", this);
+ return true;
+ }
+
+ @Override
+ public void shutdown() {
+ logger.warn("{}: shutdown", this);
+ }
+
+ @Override
+ public boolean isAlive() {
+ return false;
+ }
+
+ @Override
+ public boolean status() {
+ logger.warn("{}: status", this);
+ return false;
+ }
+
+ @Override
+ public void stateChange(PdpStateChange change) {
+ logger.warn("{}: state-change: {}", this, change);
+ return;
+ }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTest.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTest.java
new file mode 100644
index 00000000..03ca3778
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTest.java
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import lombok.ToString;
+import org.onap.policy.models.pdp.enums.PdpState;
+
+/**
+ * Lifecycle Test State.
+ */
+@ToString
+public class LifecycleStateTest extends LifecycleStateUnsupported {
+
+ /**
+ * Constructor.
+ * @param manager fsm
+ */
+ public LifecycleStateTest(LifecycleFsm manager) {
+ super(manager);
+ }
+
+ @Override
+ public PdpState state() {
+ return PdpState.TEST;
+ }
+}
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupported.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupported.java
new file mode 100644
index 00000000..ed6fa1a5
--- /dev/null
+++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupported.java
@@ -0,0 +1,78 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.lifecycle;
+
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+
+/**
+ * Support class for those unsupported states not yet implemented.
+ */
+public abstract class LifecycleStateUnsupported extends LifecycleState {
+
+ /**
+ * Constructor.
+ * @param manager Lifecycle Manager.
+ */
+ public LifecycleStateUnsupported(LifecycleFsm manager) {
+ super(manager);
+ }
+
+ @Override
+ public boolean transitionToState(LifecycleState newState) {
+ throw new UnsupportedOperationException("transitionToAction: " + this);
+ }
+
+ @Override
+ public boolean start() {
+ throw new UnsupportedOperationException("start: " + this);
+ }
+
+ @Override
+ public boolean stop() {
+ throw new UnsupportedOperationException("stop: " + this);
+ }
+
+ @Override
+ public void shutdown() {
+ throw new UnsupportedOperationException("shutdown: " + this);
+ }
+
+ @Override
+ public boolean isAlive() {
+ throw new UnsupportedOperationException("isAlive: " + this);
+ }
+
+ @Override
+ public boolean status() {
+ throw new UnsupportedOperationException("status: " + this);
+ }
+
+ @Override
+ public void update(PdpUpdate update) {
+ throw new UnsupportedOperationException("start: " + this);
+ }
+
+ @Override
+ public void stateChange(PdpStateChange change) {
+ throw new UnsupportedOperationException("start: " + this);
+ }
+}
diff --git a/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureAPI b/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureAPI
new file mode 100644
index 00000000..78cf97eb
--- /dev/null
+++ b/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureAPI
@@ -0,0 +1 @@
+org.onap.policy.drools.lifecycle.LifecycleFeature
diff --git a/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI b/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI
new file mode 100644
index 00000000..78cf97eb
--- /dev/null
+++ b/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI
@@ -0,0 +1 @@
+org.onap.policy.drools.lifecycle.LifecycleFeature
diff --git a/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI b/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI
new file mode 100644
index 00000000..78cf97eb
--- /dev/null
+++ b/feature-lifecycle/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureAPI
@@ -0,0 +1 @@
+org.onap.policy.drools.lifecycle.LifecycleFeature