Track policies when active.
[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 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.drools.lifecycle;
22
23 import java.util.List;
24 import java.util.function.BiFunction;
25 import lombok.NonNull;
26 import org.onap.policy.drools.system.PolicyController;
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(LifecycleState.class);
43
44     protected abstract boolean stateChangeToPassive(@NonNull PdpStateChange change);
45
46     protected abstract boolean stateChangeToActive(@NonNull PdpStateChange change);
47
48     protected abstract boolean deployPolicy(@NonNull PolicyController controller, @NonNull ToscaPolicy policy);
49
50     protected abstract boolean undeployPolicy(@NonNull PolicyController controller, @NonNull ToscaPolicy policy);
51
52     protected LifecycleStateRunning(LifecycleFsm manager) {
53         super(manager);
54     }
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             return fsm.statusAction();
83         }
84     }
85
86     @Override
87     public boolean isAlive() {
88         return true;
89     }
90
91     @Override
92     public boolean stateChange(@NonNull PdpStateChange change) {
93         synchronized (fsm) {
94             if (change.getState() == PdpState.PASSIVE) {
95                 return stateChangeToPassive(change);
96             }
97
98             if (change.getState() == PdpState.ACTIVE) {
99                 return stateChangeToActive(change);
100             }
101
102             logger.warn("{}: state-change: {}", this, change);
103
104             invalidStateChange(change);
105             return false;
106         }
107     }
108
109     @Override
110     public boolean update(@NonNull PdpUpdate update) {
111         synchronized (fsm) {
112             if (update.getPdpHeartbeatIntervalMs() != null
113                     && !fsm.setStatusIntervalAction(update.getPdpHeartbeatIntervalMs() / 1000)) {
114                 fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.FAIL,
115                     "invalid interval: " + update.getPdpHeartbeatIntervalMs() + " seconds"));
116                 return false;
117             }
118
119             fsm.setGroupAction(update.getPdpGroup(), update.getPdpSubgroup());
120
121             if (!updatePolicies(update.getPolicies())) {
122                 fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.FAIL, "cannot process policies"));
123                 return false;
124             }
125
126             return fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.SUCCESS, null));
127         }
128     }
129
130     protected boolean updatePolicies(List<ToscaPolicy> policies) {
131         if (policies == null) {
132             return true;
133         }
134
135         // Note that PAP sends the list of all ACTIVE policies with every
136         // UPDATE message.   First, we will undeploy all policies that are
137         // running but are not present in this list.  This will include
138         // policies that are overridden by a different version.   Second,
139         // we will deploy those policies that are not installed but
140         // resent in this list.
141
142         boolean success = undeployPolicies(policies);
143         return deployPolicies(policies) && success;
144     }
145
146     protected boolean deployPolicies(List<ToscaPolicy> policies) {
147         return syncPolicies(fsm.getDeployablePoliciesAction(policies), this::deployPolicy);
148     }
149
150     protected boolean undeployPolicies(List<ToscaPolicy> policies) {
151         return syncPolicies(fsm.getUndeployablePoliciesAction(policies), this::undeployPolicy);
152     }
153
154     protected boolean syncPolicies(List<ToscaPolicy> policies,
155                                    BiFunction<PolicyController, ToscaPolicy, Boolean> sync) {
156         boolean success = true;
157         for (ToscaPolicy policy : policies) {
158             ToscaPolicyTypeIdentifier policyType = policy.getTypeIdentifier();
159             PolicyController controller = fsm.getController(policyType);
160             if (controller == null) {
161                 logger.warn("no controller found for {}", policyType);
162                 success = false;
163                 continue;
164             }
165
166             success = sync.apply(controller, policy) && success;
167         }
168
169         return success;
170     }
171
172     private void invalidStateChange(PdpStateChange change) {
173         logger.warn("{}: state-change: {}", this, change);
174         fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.FAIL,
175                  "invalid state change to " + change.getState()));
176     }
177
178     protected PdpResponseDetails response(String requestId, PdpResponseStatus responseStatus, String message) {
179         PdpResponseDetails response = new PdpResponseDetails();
180         response.setResponseTo(requestId);
181         response.setResponseStatus(responseStatus);
182         if (message != null) {
183             response.setResponseMessage(message);
184         }
185
186         return response;
187     }
188 }