Fix the get loop state logic
[clamp.git] / src / main / java / org / onap / clamp / loop / LoopOperation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights
6  *                             reserved.
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  */
23
24 package org.onap.clamp.loop;
25
26 import com.att.eelf.configuration.EELFLogger;
27 import com.att.eelf.configuration.EELFManager;
28 import com.google.gson.JsonArray;
29 import com.google.gson.JsonElement;
30 import com.google.gson.JsonNull;
31 import com.google.gson.JsonObject;
32 import com.google.gson.JsonPrimitive;
33
34 import java.io.IOException;
35 import java.lang.reflect.Array;
36 import java.util.Collection;
37 import java.util.Map;
38
39 import org.apache.camel.Exchange;
40 import org.apache.camel.Message;
41 import org.json.simple.JSONObject;
42 import org.json.simple.parser.JSONParser;
43 import org.json.simple.parser.ParseException;
44 import org.onap.clamp.clds.config.ClampProperties;
45 import org.springframework.beans.factory.annotation.Autowired;
46 import org.springframework.stereotype.Component;
47 import org.yaml.snakeyaml.Yaml;
48
49 /**
50  * Closed loop operations.
51  */
52 @Component
53 public class LoopOperation {
54
55     protected static final EELFLogger logger = EELFManager.getInstance().getLogger(LoopOperation.class);
56     protected static final EELFLogger auditLogger = EELFManager.getInstance().getMetricsLogger();
57     private static final String DCAE_LINK_FIELD = "links";
58     private static final String DCAE_STATUS_FIELD = "status";
59     private static final String DCAE_DEPLOYMENT_TEMPLATE = "dcae.deployment.template";
60     private static final String DCAE_SERVICETYPE_ID = "serviceTypeId";
61     private static final String DCAE_INPUTS = "inputs";
62     private static final String DCAE_DEPLOYMENT_PREFIX = "closedLoop_";
63     private static final String DCAE_DEPLOYMENT_SUFIX = "_deploymentId";
64     private final LoopService loopService;
65     private final ClampProperties refProp;
66
67     public enum TempLoopState {
68         NOT_SUBMITTED, SUBMITTED, DEPLOYED, NOT_DEPLOYED, PROCESSING, IN_ERROR;
69     }
70
71     /**
72      * The constructor.
73      * @param loopService The loop service
74      * @param refProp The clamp properties
75      */
76     @Autowired
77     public LoopOperation(LoopService loopService, ClampProperties refProp) {
78         this.loopService = loopService;
79         this.refProp = refProp;
80     }
81
82     /**
83      * Get the payload used to send the deploy closed loop request.
84      *
85      * @param loop The loop
86      * @return The payload used to send deploy closed loop request
87      * @throws IOException IOException
88      */
89     public String getDeployPayload(Loop loop) throws IOException {
90         Yaml yaml = new Yaml();
91         Map<String, Object> yamlMap = yaml.load(loop.getBlueprint());
92         JsonObject bluePrint = wrapSnakeObject(yamlMap).getAsJsonObject();
93
94         String serviceTypeId = loop.getDcaeBlueprintId();
95
96         JsonObject rootObject = refProp.getJsonTemplate(DCAE_DEPLOYMENT_TEMPLATE).getAsJsonObject();
97         rootObject.addProperty(DCAE_SERVICETYPE_ID, serviceTypeId);
98         if (bluePrint != null) {
99             rootObject.add(DCAE_INPUTS, bluePrint);
100         }
101         String apiBodyString = rootObject.toString();
102         logger.info("Dcae api Body String - " + apiBodyString);
103
104         return apiBodyString;
105     }
106
107     /**
108      * Get the deployment id.
109      *
110      * @param loop The loop
111      * @return The deployment id
112      * @throws IOException IOException
113      */
114     public String getDeploymentId(Loop loop) {
115         // Set the deploymentId if not present yet
116         String deploymentId = "";
117         // If model is already deployed then pass same deployment id
118         if (loop.getDcaeDeploymentId() != null && !loop.getDcaeDeploymentId().isEmpty()) {
119             deploymentId = loop.getDcaeDeploymentId();
120         } else {
121             deploymentId = DCAE_DEPLOYMENT_PREFIX + loop.getName() + DCAE_DEPLOYMENT_SUFIX;
122         }
123         return deploymentId;
124     }
125
126     /**
127      * Update the loop info.
128      *
129      * @param camelExchange The camel exchange
130      * @param loop The loop
131      * @param deploymentId The deployment id
132      * @throws ParseException The parse exception
133      */
134     public void updateLoopInfo(Exchange camelExchange, Loop loop, String deploymentId) throws ParseException {
135         Message in = camelExchange.getIn();
136         String msg = in.getBody(String.class);
137
138         JSONParser parser = new JSONParser();
139         Object obj0 = parser.parse(msg);
140         JSONObject jsonObj = (JSONObject) obj0;
141
142         JSONObject linksObj = (JSONObject) jsonObj.get(DCAE_LINK_FIELD);
143         String statusUrl = (String) linksObj.get(DCAE_STATUS_FIELD);
144
145         // use http4 instead of http, because camel http4 component is used to do the http call
146         statusUrl.replace("http", "http4");
147
148         loop.setDcaeDeploymentId(deploymentId);
149         loop.setDcaeDeploymentStatusUrl(statusUrl);
150         loopService.saveOrUpdateLoop(loop);
151     }
152
153     /**
154      * Get the Closed Loop status based on the reply from Policy.
155      *
156      * @param statusCode The status code
157      * @return The state based on policy response
158      * @throws ParseException The parse exception
159      */
160     public String analysePolicyResponse(int statusCode) throws ParseException {
161         if (statusCode == 200) {
162             return TempLoopState.SUBMITTED.toString();
163         } else if (statusCode == 404) {
164             return TempLoopState.NOT_SUBMITTED.toString();
165         }
166         return TempLoopState.IN_ERROR.toString();
167     }
168
169     /**
170      * Get the Closed Loop status based on the reply from DCAE.
171      *
172      * @param camelExchange The camel exchange
173      * @return The state based on DCAE response
174      * @throws ParseException The parse exception
175      */
176     public String analyseDcaeResponse(Exchange camelExchange, Integer statusCode) throws ParseException {
177         if (statusCode == null) {
178             return TempLoopState.NOT_DEPLOYED.toString();
179         }
180         if (statusCode == 200) {
181             Message in = camelExchange.getIn();
182             String msg = in.getBody(String.class);
183
184             JSONParser parser = new JSONParser();
185             Object obj0 = parser.parse(msg);
186             JSONObject jsonObj = (JSONObject) obj0;
187
188             String opType = (String) jsonObj.get("operationType");
189             String status = (String) jsonObj.get("status");
190
191             // status = processing/successded/failed
192             if (status == "successed") {
193                 if (opType == "install") {
194                     return TempLoopState.DEPLOYED.toString();
195                 } else if (status == "successed") {
196                     return TempLoopState.NOT_DEPLOYED.toString();
197                 }
198             } else if (status == "processing") {
199                 return TempLoopState.PROCESSING.toString();
200             }
201         } else if (statusCode == 404) {
202             return TempLoopState.NOT_DEPLOYED.toString();
203         }
204         return TempLoopState.IN_ERROR.toString();
205     }
206
207     /**
208      * Get the status of the closed loop based on the response from Policy and DCAE.
209      *
210      * @param policyState The state get from Policy
211      * @param dcaeState The state get from DCAE
212      * @throws ParseException The parse exception
213      */
214     public LoopState updateLoopStatus(TempLoopState policyState, TempLoopState dcaeState) {
215         LoopState clState = LoopState.IN_ERROR;
216         if (policyState == TempLoopState.SUBMITTED) {
217             if (dcaeState == TempLoopState.DEPLOYED) {
218                 clState = LoopState.DEPLOYED;
219             } else if (dcaeState == TempLoopState.PROCESSING) {
220                 clState = LoopState.WAITING;
221             } else if (dcaeState == TempLoopState.NOT_DEPLOYED) {
222                 clState = LoopState.SUBMITTED;
223             }
224         } else if (policyState == TempLoopState.NOT_SUBMITTED) {
225             if (dcaeState == TempLoopState.NOT_DEPLOYED) {
226                 clState = LoopState.DESIGN;
227             }
228         }
229         return clState;
230     }
231
232     private JsonElement wrapSnakeObject(Object obj) {
233         // NULL => JsonNull
234         if (obj == null) {
235             return JsonNull.INSTANCE;
236         }
237
238         // Collection => JsonArray
239         if (obj instanceof Collection) {
240             JsonArray array = new JsonArray();
241             for (Object childObj : (Collection<?>) obj) {
242                 array.add(wrapSnakeObject(childObj));
243             }
244             return array;
245         }
246
247         // Array => JsonArray
248         if (obj.getClass().isArray()) {
249             JsonArray array = new JsonArray();
250
251             int length = Array.getLength(array);
252             for (int i = 0; i < length; i++) {
253                 array.add(wrapSnakeObject(Array.get(array, i)));
254             }
255             return array;
256         }
257
258         // Map => JsonObject
259         if (obj instanceof Map) {
260             Map<?, ?> map = (Map<?, ?>) obj;
261
262             JsonObject jsonObject = new JsonObject();
263             for (final Map.Entry<?, ?> entry : map.entrySet()) {
264                 final String name = String.valueOf(entry.getKey());
265                 final Object value = entry.getValue();
266                 jsonObject.add(name, wrapSnakeObject(value));
267             }
268             return jsonObject;
269         }
270
271         // otherwise take it as a string
272         return new JsonPrimitive(String.valueOf(obj));
273     }
274
275 }