block status operations until controllers ready
[policy/drools-pdp.git] / feature-lifecycle / src / main / java / org / onap / policy / drools / lifecycle / LifecycleStateRunning.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019 Bell Canada.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.drools.lifecycle;
23
24 import java.util.List;
25 import java.util.function.BiPredicate;
26 import lombok.NonNull;
27 import org.onap.policy.models.pdp.concepts.PdpResponseDetails;
28 import org.onap.policy.models.pdp.concepts.PdpStateChange;
29 import org.onap.policy.models.pdp.concepts.PdpUpdate;
30 import org.onap.policy.models.pdp.enums.PdpResponseStatus;
31 import org.onap.policy.models.pdp.enums.PdpState;
32 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
33 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * Support class for default functionality for running states.
39  */
40 public abstract class LifecycleStateRunning extends LifecycleStateDefault {
41
42     private static final Logger logger = LoggerFactory.getLogger(LifecycleStateRunning.class);
43
44     protected LifecycleStateRunning(LifecycleFsm manager) {
45         super(manager);
46     }
47
48     protected abstract boolean stateChangeToPassive(@NonNull PdpStateChange change);
49
50     protected abstract boolean stateChangeToActive(@NonNull PdpStateChange change);
51
52     protected abstract boolean deployPolicy(@NonNull PolicyTypeController controller, @NonNull ToscaPolicy policy);
53
54     protected abstract boolean undeployPolicy(@NonNull PolicyTypeController controller, @NonNull ToscaPolicy policy);
55
56     @Override
57     public boolean start() {
58         logger.warn("{}: start", this);
59         return false;
60     }
61
62     @Override
63     public boolean stop() {
64         synchronized (fsm) {
65             boolean success = fsm.statusAction(PdpState.TERMINATED, null);
66             success = fsm.stopAction() && success;
67             return transitionToState(new LifecycleStateTerminated(fsm)) && success;
68         }
69     }
70
71     @Override
72     public void shutdown() {
73         synchronized (fsm) {
74             stop();
75             fsm.shutdownAction();
76         }
77     }
78
79     @Override
80     public boolean status() {
81         synchronized (fsm) {
82             if (!fsm.isMandatoryPolicyTypesCompliant()) {
83                 logger.info("Not all expected policy types are registered yet, current={}, expected={}",
84                         fsm.getCurrentPolicyTypes(), fsm.getMandatoryPolicyTypes());
85                 return false;
86             }
87
88             return fsm.statusAction();
89         }
90     }
91
92     @Override
93     public boolean isAlive() {
94         return true;
95     }
96
97     @Override
98     public boolean stateChange(@NonNull PdpStateChange change) {
99         synchronized (fsm) {
100             if (change.getState() == PdpState.PASSIVE) {
101                 return stateChangeToPassive(change);
102             }
103
104             if (change.getState() == PdpState.ACTIVE) {
105                 return stateChangeToActive(change);
106             }
107
108             logger.warn("{}: state-change: {}", this, change);
109
110             invalidStateChange(change);
111             return false;
112         }
113     }
114
115     @Override
116     public boolean update(@NonNull PdpUpdate update) {
117         synchronized (fsm) {
118             if (update.getPdpHeartbeatIntervalMs() != null
119                     && !fsm.setStatusIntervalAction(update.getPdpHeartbeatIntervalMs() / 1000)) {
120                 fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.FAIL,
121                     "invalid interval: " + update.getPdpHeartbeatIntervalMs() + " seconds"));
122                 return false;
123             }
124
125             fsm.setSubGroupAction(update.getPdpSubgroup());
126
127             if (!updatePolicies(update.getPolicies())) {
128                 fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.FAIL, "cannot process policies"));
129                 return false;
130             }
131
132             return fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.SUCCESS, null));
133         }
134     }
135
136     @Override
137     public boolean updatePolicies(List<ToscaPolicy> policies) {
138         if (policies == null) {
139             return true;
140         }
141
142         // Note that PAP sends the list of all ACTIVE policies with every
143         // UPDATE message.   First, we will undeploy all policies that are
144         // running but are not present in this list.  This will include
145         // policies that are overridden by a different version.   Second,
146         // we will deploy those policies that are not installed but
147         // included in this list.
148
149         boolean success = undeployPolicies(policies);
150         return deployPolicies(policies) && success;
151     }
152
153     protected boolean deployPolicies(List<ToscaPolicy> policies) {
154         return syncPolicies(fsm.getDeployablePoliciesAction(policies), this::deployPolicy);
155     }
156
157     protected boolean undeployPolicies(List<ToscaPolicy> policies) {
158         return syncPolicies(fsm.getUndeployablePoliciesAction(policies), this::undeployPolicy);
159     }
160
161     protected boolean syncPolicies(List<ToscaPolicy> policies,
162                                    BiPredicate<PolicyTypeController, ToscaPolicy> sync) {
163         boolean success = true;
164         for (ToscaPolicy policy : policies) {
165             ToscaPolicyTypeIdentifier policyType = policy.getTypeIdentifier();
166             PolicyTypeController controller = fsm.getController(policyType);
167             if (controller == null) {
168                 logger.warn("no controller found for {}", policyType);
169                 success = false;
170                 continue;
171             }
172
173             success = fsm.getDomainMaker().isConformant(policy) && sync.test(controller, policy) && success;
174         }
175
176         return success;
177     }
178
179     private void invalidStateChange(PdpStateChange change) {
180         logger.warn("{}: state-change: {}", this, change);
181         fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.FAIL,
182                  "invalid state change to " + change.getState()));
183     }
184
185     protected PdpResponseDetails response(String requestId, PdpResponseStatus responseStatus, String message) {
186         PdpResponseDetails response = new PdpResponseDetails();
187         response.setResponseTo(requestId);
188         response.setResponseStatus(responseStatus);
189         if (message != null) {
190             response.setResponseMessage(message);
191         }
192
193         return response;
194     }
195 }