7b6f13611c83e4d4fca450a60ebe4b48502c1a5e
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.database.operationshistory;
22
23 import com.att.research.xacml.api.XACML3;
24 import com.att.research.xacml.api.pip.PIPException;
25 import com.att.research.xacml.api.pip.PIPFinder;
26 import com.att.research.xacml.api.pip.PIPRequest;
27 import com.att.research.xacml.api.pip.PIPResponse;
28 import com.att.research.xacml.std.pip.StdMutablePIPResponse;
29 import com.att.research.xacml.std.pip.StdPIPResponse;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashSet;
34 import java.util.Properties;
35 import java.util.Set;
36 import org.onap.policy.database.ToscaDictionary;
37 import org.onap.policy.database.std.StdOnapPip;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41
42 public class CountRecentOperationsPip extends StdOnapPip {
43     public static final String ISSUER_NAME = "count-recent-operations";
44     private static Logger logger = LoggerFactory.getLogger(CountRecentOperationsPip.class);
45
46     private static final Set<String> TIME_WINDOW_SCALES = Collections
47                     .unmodifiableSet(new HashSet<>(Arrays.asList("minute", "hour", "day", "week", "month", "year")));
48
49     public CountRecentOperationsPip() {
50         super();
51     }
52
53     @Override
54     public Collection<PIPRequest> attributesRequired() {
55         return Arrays.asList(PIP_REQUEST_ACTOR, PIP_REQUEST_RECIPE, PIP_REQUEST_TARGET);
56     }
57
58     @Override
59     public void configure(String id, Properties properties) throws PIPException {
60         super.configure(id, properties, ISSUER_NAME);
61     }
62
63     /**
64      * getAttributes.
65      *
66      * @param pipRequest the request
67      * @param pipFinder the pip finder
68      * @return PIPResponse
69      */
70     @Override
71     public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
72         logger.debug("getAttributes requesting attribute {} of type {} for issuer {}",
73                 pipRequest.getAttributeId(), pipRequest.getDataTypeId(), pipRequest.getIssuer());
74
75         if (isRequestInvalid(pipRequest)) {
76             return StdPIPResponse.PIP_RESPONSE_EMPTY;
77         }
78
79         //
80         // Parse out the issuer which denotes the time window
81         // Eg: any-prefix:tw:10:minute
82         //
83         String[] s1 = pipRequest.getIssuer().split("tw:");
84         String[] s2 = s1[1].split(":");
85         int timeWindowVal = Integer.parseInt(s2[0]);
86         String timeWindowScale = s2[1];
87         //
88         // Grab other attribute values
89         //
90         String actor = getActor(pipFinder);
91         String operation = getRecipe(pipFinder);
92         String target = getTarget(pipFinder);
93         String timeWindow = timeWindowVal + " " + timeWindowScale;
94         logger.info("Going to query DB about: actor {} operation {} target {} time window {}",
95                 actor, operation, target, timeWindow);
96         //
97         // Sanity check
98         //
99         if (actor == null || operation == null || target == null) {
100             //
101             // See if we have all the values
102             //
103             logger.error("missing attributes return empty");
104             return StdPIPResponse.PIP_RESPONSE_EMPTY;
105         }
106         //
107         // Ok do the database query
108         //
109         int operationCount = doDatabaseQuery(actor, operation, target, timeWindowVal, timeWindowScale);
110         //
111         // Create and return PipResponse
112         //
113         StdMutablePIPResponse pipResponse    = new StdMutablePIPResponse();
114         this.addIntegerAttribute(pipResponse,
115                 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
116                 ToscaDictionary.ID_RESOURCE_GUARD_OPERATIONCOUNT,
117                 operationCount,
118                 pipRequest);
119         return new StdPIPResponse(pipResponse);
120     }
121
122     private int doDatabaseQuery(String actor, String operation, String target, int timeWindowVal,
123             String timeWindowScale) {
124         logger.info("Querying operations history for {} {} {} {} {}",
125                 actor, operation, target, timeWindowVal, timeWindowScale);
126         if (em == null) {
127             logger.error("No EntityManager available");
128             return -1;
129         }
130         //
131         // Compute the time window
132         //
133         if (! TIME_WINDOW_SCALES.contains(timeWindowScale.toLowerCase())) {
134             //
135             // Unsupported
136             //
137             logger.error("Unsupported time window scale value {}", timeWindowScale);
138             //
139             // Throw an exception instead?
140             //
141             return -1;
142         }
143         //
144         // Do the query
145         //
146         Object result = null;
147         try {
148             //
149             // Set up query --- operationshistory is magic, should fix sometime
150             //
151             String strQuery = "select count(*) as numops from operationshistory"
152                 + " where outcome<>'Failure_Guard'"
153                 + " and actor=?"
154                 + " and operation=?"
155                 + " and target=?"
156                 + " and endtime between"
157                 + " TIMESTAMPADD(?, ?, CURRENT_TIMESTAMP)"
158                 + " and CURRENT_TIMESTAMP";
159             //
160             // We are expecting a single result
161             //
162             result = em.createNativeQuery(strQuery)
163                 .setParameter(1, actor)
164                 .setParameter(2, operation)
165                 .setParameter(3, target)
166                 .setParameter(4, timeWindowScale)
167                 .setParameter(5, timeWindowVal * -1)
168                 .getSingleResult();
169         } catch (RuntimeException e) {
170             logger.error("Named query failed ", e);
171         }
172         //
173         // Check our query results
174         //
175         if (result != null) {
176             //
177             // Success let's see what JPA returned to us
178             //
179             logger.info("operations query returned {}", result);
180             //
181             // Should get back a number
182             //
183             if (result instanceof Number) {
184                 return ((Number) result).intValue();
185             }
186             //
187             // We shouldn't really get this result, but just
188             // in case we'll do the dirty work of parsing the
189             // string representation of the object.
190             //
191             return Integer.parseInt(result.toString());
192         }
193         //
194         // We get here if we didn't get a result. Should
195         // we propagate back an exception?
196         //
197         return -1;
198     }
199
200 }