Handle pap update messages 32/84132/2
authorjhh <jorge.hernandez-herrero@att.com>
Wed, 3 Apr 2019 18:18:14 +0000 (13:18 -0500)
committerjhh <jorge.hernandez-herrero@att.com>
Thu, 4 Apr 2019 12:48:12 +0000 (07:48 -0500)
Addressing feedback from previos review.

Issue-ID: POLICY-1608
Change-Id: I8e36c99b13a3eb81c72515c039e86aa9e32e6f14
Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleState.java
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateDefault.java
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java [new file with mode: 0644]
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminated.java
feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupported.java
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java
feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminatedTest.java

index 61f6de9..7437568 100644 (file)
@@ -22,8 +22,8 @@ package org.onap.policy.drools.lifecycle;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.Properties;
-import java.util.UUID;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
@@ -44,9 +44,11 @@ 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.PdpResponseDetails;
 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.concepts.PdpUpdate;
+import org.onap.policy.models.pdp.concepts.ToscaPolicyTypeIdentifier;
 import org.onap.policy.models.pdp.enums.PdpHealthStatus;
 import org.onap.policy.models.pdp.enums.PdpMessageType;
 import org.onap.policy.models.pdp.enums.PdpState;
@@ -61,6 +63,7 @@ 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 long MIN_STATUS_INTERVAL_SECONDS = 5L;
     protected static final String PDP_MESSAGE_NAME = "messageName";
 
     private static final Logger logger = LoggerFactory.getLogger(LifecycleFsm.class);
@@ -70,6 +73,9 @@ public class LifecycleFsm implements Startable {
     protected TopicSource source;
     protected TopicSinkClient client;
 
+    @Getter
+    protected final String name = NetworkUtil.getHostname();
+
     protected volatile LifecycleState state = new LifecycleStateTerminated(this);
 
     @GsonJsonIgnore
@@ -82,17 +88,20 @@ public class LifecycleFsm implements Startable {
     protected MessageTypeDispatcher sourceDispatcher = new MessageTypeDispatcher(new String[]{PDP_MESSAGE_NAME});
 
     @GsonJsonIgnore
-    protected MessageNameDispatcher nameDispatcher = new MessageNameDispatcher(PdpStateChange.class, this);
+    protected PdpStateChangeFeed stateChangeFeed = new PdpStateChangeFeed(PdpStateChange.class, this);
+
+    @GsonJsonIgnore
+    protected PdpUpdateFeed updateFeed = new PdpUpdateFeed(PdpUpdate.class, this);
 
     @Getter
     @Setter
     protected long statusTimerSeconds = DEFAULT_STATUS_TIMER_SECONDS;
 
     @Getter
-    protected String pdpGroup;
+    protected String group;
 
     @Getter
-    protected String pdpSubgroup;
+    protected String subgroup;
 
     /**
      * Constructor.
@@ -146,11 +155,15 @@ public class LifecycleFsm implements Startable {
         return state.status();
     }
 
-    public synchronized void stateChange(PdpStateChange stateChange) {
+    public synchronized boolean stateChange(PdpStateChange stateChange) {
         logger.info("lifecycle event: state-change");
-        state.stateChange(stateChange);
+        return state.stateChange(stateChange);
     }
 
+    public synchronized boolean update(PdpUpdate update) {
+        logger.info("lifecycle event: update");
+        return state.update(update);
+    }
     /* ** FSM State Actions ** */
 
     protected boolean startAction() {
@@ -176,23 +189,51 @@ public class LifecycleFsm implements Startable {
         shutdownTimers();
     }
 
-    protected boolean statusAction(PdpState state) {
+    protected boolean statusAction() {
+        return statusAction(state(), null);
+    }
+
+    protected boolean statusAction(PdpResponseDetails response) {
+        return statusAction(state(), response);
+    }
+
+    protected boolean statusAction(PdpState state, PdpResponseDetails response) {
         if (!isAlive()) {
             return false;
         }
 
+        PdpStatus status = statusPayload(state);
+        if (response != null) {
+            status.setRequestId(response.getResponseTo());     // for standard logging of transactions
+            status.setResponse(response);
+        }
+
         return client.send(statusPayload(state));
     }
 
     protected void setGroupAction(String group, String subgroup) {
-        this.pdpGroup = group;
-        this.pdpSubgroup = subgroup;
+        this.group = group;
+        this.subgroup = subgroup;
     }
 
     protected void transitionToAction(@NonNull LifecycleState newState) {
         state = newState;
     }
 
+    protected boolean setStatusIntervalAction(long intervalSeconds) {
+        if (intervalSeconds == statusTimerSeconds || intervalSeconds == 0) {
+            return true;
+        }
+
+        if (intervalSeconds <= MIN_STATUS_INTERVAL_SECONDS) {
+            logger.warn("interval is too low (< {}): {}", MIN_STATUS_INTERVAL_SECONDS, intervalSeconds);
+            return false;
+        }
+
+        setStatusTimerSeconds(intervalSeconds);
+        return stopTimers() && startTimers();
+    }
+
     /* ** Action Helpers ** */
 
     private boolean startIo() {
@@ -230,14 +271,19 @@ public class LifecycleFsm implements Startable {
         scheduler.shutdownNow();
     }
 
-    private PdpStatus statusPayload(PdpState state) {
+    private PdpStatus statusPayload() {
+        return statusPayload(state());
+    }
+
+    private PdpStatus statusPayload(@NonNull PdpState state) {
         PdpStatus status = new PdpStatus();
-        status.setRequestId(UUID.randomUUID().toString());
-        status.setTimestampMs(System.currentTimeMillis());
-        status.setInstance(NetworkUtil.getHostname());
+        status.setName(name);
+        status.setPdpGroup(group);
+        status.setPdpSubgroup(subgroup);
         status.setState(state);
         status.setHealthy(isAlive() ? PdpHealthStatus.HEALTHY : PdpHealthStatus.NOT_HEALTHY);
         status.setPdpType("drools");    // TODO: enum ?
+        status.setSupportedPolicyTypes(getCapabilities());
         return status;
     }
 
@@ -253,7 +299,8 @@ public class LifecycleFsm implements Startable {
 
         this.source = sources.get(0);
         this.source.register(this.sourceDispatcher);
-        this.sourceDispatcher.register(PdpMessageType.PDP_STATE_CHANGE.name(), nameDispatcher);
+        this.sourceDispatcher.register(PdpMessageType.PDP_STATE_CHANGE.name(), stateChangeFeed);
+        this.sourceDispatcher.register(PdpMessageType.PDP_UPDATE.name(), updateFeed);
         return source.start();
     }
 
@@ -272,8 +319,8 @@ public class LifecycleFsm implements Startable {
         return this.client.getSink().start();
     }
 
-    private List<PolicyTypeIdent> getCapabilities() {
-        List<PolicyTypeIdent> capabilities = new ArrayList<>();
+    private List<ToscaPolicyTypeIdentifier> getCapabilities() {
+        List<ToscaPolicyTypeIdentifier> capabilities = new ArrayList<>();
         for (DroolsController dc : DroolsController.factory.inventory()) {
             if (!dc.isBrained()) {
                 continue;
@@ -282,7 +329,7 @@ public class LifecycleFsm implements Startable {
             for (String domain : dc.getBaseDomainNames()) {
                 // HACK: until legacy controllers are removed
                 if (StringUtils.countMatches(domain, ".") > 1) {
-                    capabilities.add(new PolicyTypeIdent(domain, POLICY_TYPE_VERSION));
+                    capabilities.add(new ToscaPolicyTypeIdentifier(domain, POLICY_TYPE_VERSION));
                 } else {
                     logger.info("legacy controller {} with domain {}", dc.getCanonicalSessionNames(), domain);
                 }
@@ -291,35 +338,81 @@ public class LifecycleFsm implements Startable {
         return capabilities;
     }
 
+    protected boolean isItMe(String name, String group, String subgroup) {
+        if (Objects.equals(name, getName())) {
+            return true;
+        }
+
+        return name == null && group != null
+            && Objects.equals(group, getGroup())
+            && Objects.equals(subgroup, getSubgroup());
+    }
 
     /* **** IO listeners ***** */
 
     /**
      * PDP State Change Message Listener.
      */
-    public static class MessageNameDispatcher extends ScoListener<PdpStateChange> {
+    public static class PdpStateChangeFeed extends ScoListener<PdpStateChange> {
 
         protected final LifecycleFsm fsm;
 
-        /**
-         * Constructor.
-         */
-        public MessageNameDispatcher(Class<PdpStateChange> clazz, LifecycleFsm fsm) {
+        protected PdpStateChangeFeed(Class<PdpStateChange> clazz, LifecycleFsm fsm) {
             super(clazz);
             this.fsm = fsm;
         }
 
         @Override
-        public void onTopicEvent(CommInfrastructure commInfrastructure, String topic,
-            StandardCoderObject standardCoderObject, PdpStateChange pdpStateChange) {
+        public void onTopicEvent(CommInfrastructure comm, String topic,
+                                 StandardCoderObject coder, PdpStateChange stateChange) {
 
-            if (pdpStateChange == null) {
-                logger.warn("pdp-state-chage null from {}:{}", commInfrastructure, topic);
+            if (!isMine(stateChange)) {
+                logger.warn("pdp-state-chage from {}:{} is invalid: {}", comm, topic, stateChange);
                 return;
             }
 
-            fsm.stateChange(pdpStateChange);
+            fsm.stateChange(stateChange);
+        }
+
+        protected boolean isMine(PdpStateChange change) {
+            if (change == null) {
+                return false;
+            }
+
+            return fsm.isItMe(change.getName(), change.getPdpGroup(), change.getPdpSubgroup());
         }
     }
 
+    /**
+     * PDP Update Message Listener.
+     */
+    public static class PdpUpdateFeed extends ScoListener<PdpUpdate> {
+
+        protected final LifecycleFsm fsm;
+
+        public PdpUpdateFeed(Class<PdpUpdate> clazz, LifecycleFsm fsm) {
+            super(clazz);
+            this.fsm = fsm;
+        }
+
+        @Override
+        public void onTopicEvent(CommInfrastructure comm, String topic,
+                                 StandardCoderObject coder, PdpUpdate update) {
+
+            if (!isMine(update)) {
+                logger.warn("pdp-update from {}:{} is invalid: {}", comm, topic, update);
+                return;
+            }
+
+            fsm.update(update);
+        }
+
+        protected boolean isMine(PdpUpdate update) {
+            if (update == null) {
+                return false;
+            }
+
+            return fsm.isItMe(update.getName(), update.getPdpGroup(), update.getPdpSubgroup());
+        }
+    }
 }
index e07df15..2976732 100644 (file)
@@ -37,11 +37,10 @@ public abstract class LifecycleState implements Startable {
     private static final Logger logger = LoggerFactory.getLogger(LifecycleState.class);
 
     @GsonJsonIgnore
-    protected LifecycleFsm fsm;
+    protected final LifecycleFsm fsm;
 
     /**
      * Constructor.
-     * @param manager Lifecycle Manager.
      */
     public LifecycleState(@NonNull LifecycleFsm manager) {
         this.fsm = manager;
@@ -49,13 +48,11 @@ public abstract class LifecycleState implements Startable {
 
     /**
      * change state.
-     * @param newState new state
      */
     public abstract boolean transitionToState(@NonNull LifecycleState newState);
 
     /**
      * current state.
-     * @return state
      */
     public abstract PdpState state();
 
@@ -66,13 +63,11 @@ public abstract class LifecycleState implements Startable {
 
     /**
      *  update event.
-     * @param update message
      */
-    public abstract void update(@NonNull PdpUpdate update);
+    public abstract boolean update(@NonNull PdpUpdate update);
 
     /**
      * state change event .
-     * @param change message
      */
-    public abstract void stateChange(@NonNull PdpStateChange change);
+    public abstract boolean stateChange(@NonNull PdpStateChange change);
 }
\ No newline at end of file
index d5be822..9ec6865 100644 (file)
@@ -22,23 +22,16 @@ package org.onap.policy.drools.lifecycle;
 
 import lombok.ToString;
 import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.enums.PdpResponseStatus;
 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 {
+public class LifecycleStateActive extends LifecycleStateRunning {
 
-    private static final Logger logger = LoggerFactory.getLogger(LifecycleStateActive.class);
-
-    /**
-     * Constructor.
-     * @param manager fsm
-     */
-    public LifecycleStateActive(LifecycleFsm manager) {
+    protected LifecycleStateActive(LifecycleFsm manager) {
         super(manager);
     }
 
@@ -48,20 +41,14 @@ public class LifecycleStateActive extends LifecycleStateDefault {
     }
 
     @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;
-            }
+    protected boolean stateChangeToActive(PdpStateChange change) {
+        return fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.SUCCESS, null));
+    }
 
-            fsm.setGroupAction(change.getPdpGroup(), change.getPdpSubgroup());
-            fsm.transitionToAction(new LifecycleStatePassive(fsm));
-        }
+    @Override
+    protected boolean stateChangeToPassive(PdpStateChange change) {
+        fsm.transitionToAction(new LifecycleStatePassive(fsm));
+        return fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.SUCCESS, null));
     }
+
 }
index 18e4001..330d02f 100644 (file)
@@ -21,7 +21,8 @@
 package org.onap.policy.drools.lifecycle;
 
 import lombok.NonNull;
-import org.onap.policy.models.pdp.enums.PdpState;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -32,11 +33,10 @@ public abstract class LifecycleStateDefault extends LifecycleStateUnsupported {
 
     private static final Logger logger = LoggerFactory.getLogger(LifecycleState.class);
 
-    public LifecycleStateDefault(LifecycleFsm manager) {
+    protected LifecycleStateDefault(LifecycleFsm manager) {
         super(manager);
     }
 
-
     @Override
     public boolean transitionToState(@NonNull LifecycleState newState) {
         logger.info("{}: state-change from {} to {}", this, state(), newState.state());
@@ -59,30 +59,35 @@ public abstract class LifecycleStateDefault extends LifecycleStateUnsupported {
 
     @Override
     public boolean stop() {
-        synchronized (fsm) {
-            boolean success = fsm.statusAction(PdpState.TERMINATED);
-            success = fsm.stopAction() && success;
-            return transitionToState(new LifecycleStateTerminated(fsm)) && success;
-        }
+        logger.warn("{}: stop", this);
+        return true;
     }
 
     @Override
     public void shutdown() {
-        synchronized (fsm) {
-            stop();
-            fsm.shutdownAction();
-        }
+        logger.warn("{}: shutdown", this);
     }
 
     @Override
-    public boolean isAlive() {
-        return true;
+    public boolean status() {
+        logger.warn("{}: status", this);
+        return false;
     }
 
     @Override
-    public boolean status() {
-        synchronized (fsm) {
-            return fsm.statusAction(state());
-        }
+    public boolean stateChange(@NonNull PdpStateChange change) {
+        logger.warn("{}: state-change: {}", this, change);
+        return false;
+    }
+
+    @Override
+    public boolean update(@NonNull PdpUpdate update) {
+        logger.warn("{}: update: {}", this, update);
+        return false;
+    }
+
+    @Override
+    public boolean isAlive() {
+        return false;
     }
 }
index dc184e8..0720ec9 100644 (file)
@@ -22,24 +22,16 @@ package org.onap.policy.drools.lifecycle;
 
 import lombok.ToString;
 import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.enums.PdpResponseStatus;
 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);
+public class LifecycleStatePassive extends LifecycleStateRunning {
 
-    /**
-     * Constructor.
-     * @param manager fsm
-     */
-    public LifecycleStatePassive(LifecycleFsm manager) {
+    protected LifecycleStatePassive(LifecycleFsm manager) {
         super(manager);
     }
 
@@ -49,15 +41,13 @@ public class LifecycleStatePassive extends LifecycleStateDefault {
     }
 
     @Override
-    public void stateChange(PdpStateChange change) {
-        synchronized (fsm) {
-            if (change.getState() != PdpState.ACTIVE) {
-                logger.warn("{}: state-change: {}", this, change);
-                return;
-            }
+    protected boolean stateChangeToActive(PdpStateChange change) {
+        fsm.transitionToAction(new LifecycleStateActive(fsm));
+        return fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.SUCCESS,null));
+    }
 
-            fsm.setGroupAction(change.getPdpGroup(), change.getPdpSubgroup());
-            fsm.transitionToAction(new LifecycleStateActive(fsm));
-        }
+    @Override
+    protected boolean stateChangeToPassive(PdpStateChange change) {
+        return fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.SUCCESS,null));
     }
 }
diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java
new file mode 100644 (file)
index 0000000..916d155
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * ============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.List;
+import lombok.NonNull;
+import org.onap.policy.models.pdp.concepts.PdpResponseDetails;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.pdp.enums.PdpResponseStatus;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Support class for default functionality for running states.
+ */
+public abstract class LifecycleStateRunning extends LifecycleStateDefault {
+
+    private static final Logger logger = LoggerFactory.getLogger(LifecycleState.class);
+
+    protected abstract boolean stateChangeToPassive(PdpStateChange change);
+
+    protected abstract boolean stateChangeToActive(PdpStateChange change);
+
+    protected LifecycleStateRunning(LifecycleFsm manager) {
+        super(manager);
+    }
+
+    @Override
+    public boolean start() {
+        logger.warn("{}: start", this);
+        return false;
+    }
+
+    @Override
+    public boolean stop() {
+        synchronized (fsm) {
+            boolean success = fsm.statusAction(PdpState.TERMINATED, null);
+            success = fsm.stopAction() && success;
+            return transitionToState(new LifecycleStateTerminated(fsm)) && success;
+        }
+    }
+
+    @Override
+    public void shutdown() {
+        synchronized (fsm) {
+            stop();
+            fsm.shutdownAction();
+        }
+    }
+
+    @Override
+    public boolean status() {
+        synchronized (fsm) {
+            return fsm.statusAction();
+        }
+    }
+
+    @Override
+    public boolean isAlive() {
+        return true;
+    }
+
+    @Override
+    public boolean stateChange(@NonNull PdpStateChange change) {
+        synchronized (fsm) {
+            if (change.getState() == PdpState.PASSIVE) {
+                group(change.getPdpGroup(), change.getPdpSubgroup());
+                return stateChangeToPassive(change);
+            }
+
+            if (change.getState() == PdpState.ACTIVE) {
+                group(change.getPdpGroup(), change.getPdpSubgroup());
+                return stateChangeToActive(change);
+            }
+
+            logger.warn("{}: state-change: {}", this, change);
+
+            invalidStateChange(change);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean update(@NonNull PdpUpdate update) {
+        synchronized (fsm) {
+            if (!fsm.setStatusIntervalAction(update.getPdpHeartbeatIntervalMs() / 1000)) {
+                fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.FAIL,
+                    "invalid interval: " + update.getPdpHeartbeatIntervalMs() + " seconds"));
+                return false;
+            }
+
+            group(update.getPdpGroup(), update.getPdpSubgroup());
+
+            if (!updatePolicies(update.getPolicies())) {
+                fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.FAIL, "cannot process policies"));
+                return false;
+            }
+
+            return fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.SUCCESS, null));
+        }
+    }
+
+    protected boolean updatePolicies(List<ToscaPolicy> policies) {
+        // TODO
+        return true;
+    }
+
+    private void invalidStateChange(PdpStateChange change) {
+        logger.warn("{}: state-change: {}", this, change);
+        fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.FAIL,
+                 "invalid state change to " + change.getState()));
+    }
+
+    protected PdpResponseDetails response(String requestId, PdpResponseStatus responseStatus, String message) {
+        PdpResponseDetails response = new PdpResponseDetails();
+        response.setResponseTo(requestId);
+        response.setResponseStatus(responseStatus);
+        if (message != null) {
+            response.setResponseMessage(message);
+        }
+
+        return response;
+    }
+
+    protected void group(String group, String subgroup) {
+        if (group == null || subgroup == null) {
+            return;
+        }
+
+        fsm.setGroupAction(group, subgroup);
+    }
+}
index 7455349..b11d575 100644 (file)
 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.
@@ -33,8 +30,6 @@ import org.slf4j.LoggerFactory;
 @ToString
 public class LifecycleStateTerminated extends LifecycleStateDefault {
 
-    private static final Logger logger = LoggerFactory.getLogger(LifecycleStateTerminated.class);
-
     protected LifecycleStateTerminated(LifecycleFsm manager) {
         super(manager);
     }
@@ -55,32 +50,4 @@ public class LifecycleStateTerminated extends LifecycleStateDefault {
             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;
-    }
 }
index ed6fa1a..11ce7f3 100644 (file)
@@ -67,12 +67,12 @@ public abstract class LifecycleStateUnsupported extends LifecycleState {
     }
 
     @Override
-    public void update(PdpUpdate update) {
-        throw new UnsupportedOperationException("start: " + this);
+    public boolean update(PdpUpdate update) {
+        throw new UnsupportedOperationException("update: " + this);
     }
 
     @Override
-    public void stateChange(PdpStateChange change) {
-        throw new UnsupportedOperationException("start: " + this);
+    public boolean stateChange(PdpStateChange change) {
+        throw new UnsupportedOperationException("stateChange: " + this);
     }
 }
index eb83bc6..c4d47d8 100644 (file)
@@ -24,9 +24,11 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
 import static org.awaitility.Awaitility.await;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
@@ -36,10 +38,12 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.network.NetworkUtil;
 import org.onap.policy.drools.persistence.SystemPersistence;
 import org.onap.policy.drools.utils.logging.LoggerUtil;
 import org.onap.policy.models.pdp.concepts.PdpStateChange;
 import org.onap.policy.models.pdp.concepts.PdpStatus;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
 import org.onap.policy.models.pdp.enums.PdpMessageType;
 import org.onap.policy.models.pdp.enums.PdpState;
 
@@ -79,7 +83,7 @@ public class LifecycleStateActiveTest {
         change.setPdpGroup("A");
         change.setPdpSubgroup("a");
         change.setState(PdpState.ACTIVE);
-        change.setName("test");
+        change.setName(fsm.getName());
 
         fsm.source.offer(new StandardCoder().encode(change));
     }
@@ -101,8 +105,8 @@ public class LifecycleStateActiveTest {
 
     private void assertActive() {
         assertEquals(PdpState.ACTIVE, fsm.state());
-        assertEquals("A", fsm.getPdpGroup());
-        assertEquals("a", fsm.getPdpSubgroup());
+        assertEquals("A", fsm.getGroup());
+        assertEquals("a", fsm.getSubgroup());
         assertTrue(fsm.isAlive());
         await().atMost(fsm.getStatusTimerSeconds() + 1, TimeUnit.SECONDS).until(isStatus(PdpState.ACTIVE));
     }
@@ -161,17 +165,22 @@ public class LifecycleStateActiveTest {
     public void stateChange() throws CoderException {
         assertActive();
 
-        /* dup */
+        /* no name and mismatching group info */
         PdpStateChange change = new PdpStateChange();
         change.setPdpGroup("B");
         change.setPdpSubgroup("b");
         change.setState(PdpState.ACTIVE);
-        change.setName("test");
 
         fsm.source.offer(new StandardCoder().encode(change));
         assertEquals(PdpState.ACTIVE, fsm.state());
-        assertEquals("B", fsm.getPdpGroup());
-        assertEquals("b", fsm.getPdpSubgroup());
+        assertNotEquals("B", fsm.getGroup());
+        assertNotEquals("b", fsm.getSubgroup());
+
+        change.setName(fsm.getName());
+        fsm.source.offer(new StandardCoder().encode(change));
+        assertEquals(PdpState.ACTIVE, fsm.state());
+        assertEquals("B", fsm.getGroup());
+        assertEquals("b", fsm.getSubgroup());
 
         change.setState(PdpState.SAFE);
         fsm.source.offer(new StandardCoder().encode(change));
@@ -188,4 +197,26 @@ public class LifecycleStateActiveTest {
 
         fsm.shutdown();
     }
+
+    @Test
+    public void update() {
+        PdpUpdate update = new PdpUpdate();
+        update.setName(NetworkUtil.getHostname());
+        update.setPdpGroup("Z");
+        update.setPdpSubgroup("z");
+        update.setPolicies(Collections.emptyList());
+
+        long originalInterval = fsm.getStatusTimerSeconds();
+        long interval = 2 * originalInterval;
+        update.setPdpHeartbeatIntervalMs(interval * 1000L);
+
+        assertTrue(fsm.update(update));
+
+        assertEquals(PdpState.ACTIVE, fsm.state());
+        assertEquals(interval, fsm.getStatusTimerSeconds());
+        assertEquals("Z", fsm.getGroup());
+        assertEquals("z", fsm.getSubgroup());
+
+        fsm.shutdown();
+    }
 }
index fbc2eeb..376eb3a 100644 (file)
@@ -26,8 +26,10 @@ import static org.awaitility.Awaitility.await;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.util.Collections;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 import org.awaitility.core.ConditionTimeoutException;
@@ -42,6 +44,7 @@ import org.onap.policy.drools.persistence.SystemPersistence;
 import org.onap.policy.drools.utils.logging.LoggerUtil;
 import org.onap.policy.models.pdp.concepts.PdpStateChange;
 import org.onap.policy.models.pdp.concepts.PdpStatus;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
 import org.onap.policy.models.pdp.enums.PdpHealthStatus;
 import org.onap.policy.models.pdp.enums.PdpMessageType;
 import org.onap.policy.models.pdp.enums.PdpState;
@@ -161,22 +164,49 @@ public class LifecycleStatePassiveTest {
 
     @Test
     public void update() {
-        // TODO
+        PdpUpdate update = new PdpUpdate();
+        update.setName(NetworkUtil.getHostname());
+        update.setPdpGroup("Z");
+        update.setPdpSubgroup("z");
+        update.setPolicies(Collections.emptyList());
+
+        long interval = 2 * fsm.getStatusTimerSeconds();
+        update.setPdpHeartbeatIntervalMs(interval * 1000L);
+
+        assertTrue(fsm.update(update));
+
+        assertEquals(PdpState.PASSIVE, fsm.state());
+        assertEquals(interval, fsm.getStatusTimerSeconds());
+        assertEquals("Z", fsm.getGroup());
+        assertEquals("z", fsm.getSubgroup());
+        assertBasicPassive();
+
         fsm.shutdown();
     }
 
     @Test
     public void stateChange() throws CoderException {
+        /* no name */
         PdpStateChange change = new PdpStateChange();
         change.setPdpGroup("A");
         change.setPdpSubgroup("a");
         change.setState(PdpState.ACTIVE);
+
+        /* invalid name */
         change.setName("test");
+        fsm.source.offer(new StandardCoder().encode(change));
 
+        assertEquals(PdpState.PASSIVE, fsm.state());
+        assertNull(fsm.getGroup());
+        assertNull(fsm.getSubgroup());
+
+        /* correct name */
+        change.setName(fsm.getName());
         fsm.source.offer(new StandardCoder().encode(change));
-        assertEquals(PdpState.ACTIVE, fsm.state.state());
-        assertEquals("A", fsm.pdpGroup);
-        assertEquals("a", fsm.pdpSubgroup);
+
+        assertEquals(PdpState.ACTIVE, fsm.state());
+        assertEquals("A", fsm.getGroup());
+        assertEquals("a", fsm.getSubgroup());
 
         fsm.shutdown();
     }
@@ -192,17 +222,19 @@ public class LifecycleStatePassiveTest {
         assertTrue(fsm.statusTask.isCancelled());
         assertTrue(fsm.statusTask.isDone());
 
-        assertEquals(1, fsm.client.getSink().getRecentEvents().length);
-        PdpStatus status = new StandardCoder().decode(fsm.client.getSink().getRecentEvents()[0], PdpStatus.class);
+        String[] events = fsm.client.getSink().getRecentEvents();
+        PdpStatus status =
+            new StandardCoder().decode(events[events.length - 1], PdpStatus.class);
         assertEquals("drools", status.getPdpType());
         assertEquals(PdpState.TERMINATED, status.getState());
         assertEquals(PdpHealthStatus.HEALTHY, status.getHealthy());
-        assertEquals(NetworkUtil.getHostname(), status.getInstance());
+        assertEquals(NetworkUtil.getHostname(), status.getName());
+        assertEquals(fsm.getName(), status.getName());
         assertEquals(PdpMessageType.PDP_STATUS, status.getMessageName());
 
         assertThatThrownBy( () -> await()
-            .atMost(fsm.statusTimerSeconds + 5, TimeUnit.SECONDS)
-            .until(isStatus(PdpState.TERMINATED, 2))).isInstanceOf(ConditionTimeoutException.class);
+            .atMost(2 * fsm.statusTimerSeconds, TimeUnit.SECONDS)
+            .until(isStatus(PdpState.TERMINATED, events.length))).isInstanceOf(ConditionTimeoutException.class);
     }
 
     private void assertBasicPassive() {
index b77fdcd..587098f 100644 (file)
@@ -23,16 +23,20 @@ package org.onap.policy.drools.lifecycle;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.util.Collections;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.onap.policy.common.utils.network.NetworkUtil;
 import org.onap.policy.drools.persistence.SystemPersistence;
 import org.onap.policy.drools.utils.logging.LoggerUtil;
 import org.onap.policy.models.pdp.concepts.PdpStateChange;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
 import org.onap.policy.models.pdp.enums.PdpState;
 
 /**
@@ -133,7 +137,17 @@ public class LifecycleStateTerminatedTest {
 
     @Test
     public void update() {
-        // TODO
+        PdpUpdate update = new PdpUpdate();
+        update.setName(NetworkUtil.getHostname());
+        update.setPdpGroup("A");
+        update.setPdpSubgroup("a");
+        update.setPolicies(Collections.emptyList());
+        update.setPdpHeartbeatIntervalMs(2 * 600000L);
+
+        assertFalse(fsm.update(update));
+
+        assertEquals(PdpState.TERMINATED, fsm.state.state());
+        assertNotEquals((2 * 60000L) / 1000L, fsm.getStatusTimerSeconds());
     }
 
     @Test