aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/main/java/org/onap/policy/pdpx/main/XacmlState.java
blob: d67a1fadcb1dcb01a412916c5d4cb8712e3006e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*-
 * ============LICENSE_START=======================================================
 * Copyright (C) 2019, 2021-2022 AT&T Intellectual Property. All rights reserved.
 * Modifications Copyright (C) 2023 Nordix Foundation.
 * ================================================================================
 * 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.
 *
 * SPDX-License-Identifier: Apache-2.0
 * ============LICENSE_END=========================================================
 */

package org.onap.policy.pdpx.main;

import java.util.Collections;
import org.apache.commons.lang3.StringUtils;
import org.onap.policy.common.utils.network.NetworkUtil;
import org.onap.policy.models.pdp.concepts.PdpMessage;
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.PdpUpdate;
import org.onap.policy.models.pdp.enums.PdpHealthStatus;
import org.onap.policy.models.pdp.enums.PdpResponseStatus;
import org.onap.policy.models.pdp.enums.PdpState;
import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager;
import org.onap.policy.pdpx.main.startstop.XacmlPdpActivator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Current state of this XACML PDP.
 */
public class XacmlState {
    // The logger for this class
    private static final Logger LOGGER = LoggerFactory.getLogger(XacmlState.class);

    /**
     * Unique name for the xacml-pdp JVM, used in PdpStatus messages.
     */
    public static final String PDP_NAME = NetworkUtil.genUniqueName("xacml");

    /**
     * The application manager.
     */
    private final XacmlPdpApplicationManager appManager;

    /**
     * Records the current state of this PDP.
     */
    private final PdpStatus status;

    /**
     * Constructs the object, initializing the state.
     */
    public XacmlState(XacmlPdpApplicationManager appManager, String pdpGroupName, String pdpType) {
        this.appManager = appManager;

        this.status = new PdpStatus();
        this.status.setName(PDP_NAME);
        this.status.setPdpType(pdpType);
        this.status.setState(PdpState.PASSIVE);
        this.status.setPolicies(Collections.emptyList());
        this.status.setPdpGroup(pdpGroupName);
    }

    /**
     * Determines if this PDP should handle the given message.
     *
     * @param message message of interest
     * @return {@code true} if this PDP should handle the message, {@code false} otherwise
     */
    public boolean shouldHandle(PdpMessage message) {
        return message.appliesTo(status.getName(), status.getPdpGroup(), status.getPdpType());
    }

    /**
     * Generates a new heart beat message.
     *
     * @return a new heart beat message
     */
    public synchronized PdpStatus genHeartbeat() {
        // first, update status fields
        status.setHealthy(XacmlPdpActivator.getCurrent().isAlive() ? PdpHealthStatus.HEALTHY
            : PdpHealthStatus.NOT_HEALTHY);

        PdpStatus heartbeat = new PdpStatus(status);
        return heartbeat;
    }

    /**
     * Updates the internal state based on the given message.
     *
     * @param message message from which to update the internal state
     * @return a response to the message
     */
    public synchronized PdpStatus updateInternalState(PdpStateChange message) {
        LOGGER.info("set state of {} to {}", this, message.getState());
        status.setState(message.getState());

        /*
         * NOTE: Do NOT update group & subgroup as state-change requests do not set those
         * fields to indicate new values; they only set them to do broadcasts to all PDPs
         * within a group/subgroup.
         */

        PdpStatus status2 = makeResponse(message, "");

        // start/stop rest controller based on state change
        handleXacmlRestController();

        // these fields aren't needed in the response, so clear them out to avoid sending
        status2.setPolicies(null);

        return status2;
    }

    /**
     * Updates the internal state based on the given message. Assumes that the policies
     * have already been updated within the application manager.
     *
     * @param message message from which to update the internal state
     * @return a response to the message
     */
    public synchronized PdpStatus updateInternalState(PdpUpdate message, String errMessage) {
        status.setPdpSubgroup(message.getPdpSubgroup());
        status.setPolicies(appManager.getToscaPolicyIdentifiers());

        return makeResponse(message, errMessage);
    }

    /**
     * Updates the internal state to Terminated.
     *
     * @return the current PdpStatus with Terminated state
     */
    public synchronized PdpStatus terminatePdpMessage() {
        LOGGER.info("set state of {} to {}", this, PdpState.TERMINATED);
        status.setState(PdpState.TERMINATED);
        return new PdpStatus(status);
    }

    /**
     * Makes a response to the given message, based on the current state.
     *
     * @param message message for which the response should be made
     * @param errMessage the error message to be sent to PAP
     * @return a new response
     */
    private PdpStatus makeResponse(PdpMessage message, String errMessage) {
        var resp = new PdpResponseDetails();

        if (StringUtils.isBlank(errMessage)) {
            resp.setResponseStatus(PdpResponseStatus.SUCCESS);
        } else {
            resp.setResponseStatus(PdpResponseStatus.FAIL);
            resp.setResponseMessage(errMessage);
        }
        resp.setResponseTo(message.getRequestId());

        var status2 = new PdpStatus(status);
        status2.setResponse(resp);
        return status2;
    }

    /**
     * Manages the Xacml-Pdp rest controller based on the Xacml-Pdp State.
     * Current supported states:
     * ACTIVE  - rest service is running and handling requests
     * PASSIVE - rest service is not running
     */
    private void handleXacmlRestController() {
        if (status.getState() == PdpState.ACTIVE) {
            LOGGER.info("State change: {} - Starting rest controller", status.getState());
            XacmlPdpActivator.getCurrent().enableApi();
        } else if (status.getState() == PdpState.PASSIVE) {
            LOGGER.info("State change: {} - Stopping rest controller", status.getState());
            XacmlPdpActivator.getCurrent().disableApi();
        } else {
            // unsupported state
            LOGGER.warn("Unsupported state: {}", status.getState());
        }
    }
}