Merge "add new sdnc interaction"
[so.git] / bpmn / so-bpmn-infrastructure-common / src / main / groovy / org / onap / so / bpmn / infrastructure / scripts / TnAllocateNssi.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2020 Huawei Technologies Co., Ltd. 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.so.bpmn.infrastructure.scripts
22
23 import com.fasterxml.jackson.databind.ObjectMapper
24 import com.google.gson.JsonArray
25 import com.google.gson.JsonObject
26 import groovy.json.JsonSlurper
27 import org.camunda.bpm.engine.delegate.BpmnError
28 import org.camunda.bpm.engine.delegate.DelegateExecution
29 import org.onap.aai.domain.yang.ServiceInstance
30 import org.onap.aaiclient.client.aai.AAIResourcesClient
31 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
32 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
33 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types
34 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
35 import org.onap.so.bpmn.common.scripts.ExceptionUtil
36 import org.onap.so.bpmn.common.scripts.RequestDBUtil
37 import org.onap.so.bpmn.core.UrnPropertiesReader
38 import org.onap.so.bpmn.core.domain.ServiceDecomposition
39 import org.onap.so.bpmn.core.domain.ServiceProxy
40 import org.onap.so.bpmn.core.json.JsonUtils
41 import org.onap.so.db.request.beans.ResourceOperationStatus
42 import org.slf4j.Logger
43 import org.slf4j.LoggerFactory
44 import org.springframework.web.util.UriUtils
45
46 import static org.apache.commons.lang3.StringUtils.isBlank
47
48 class TnAllocateNssi extends AbstractServiceTaskProcessor {
49     String Prefix = "TNALLOC_"
50
51     ExceptionUtil exceptionUtil = new ExceptionUtil()
52     JsonUtils jsonUtil = new JsonUtils()
53     RequestDBUtil requestDBUtil = new RequestDBUtil()
54     JsonSlurper jsonSlurper = new JsonSlurper()
55     ObjectMapper objectMapper = new ObjectMapper()
56     TnNssmfUtils tnNssmfUtils = new TnNssmfUtils()
57     private static final Logger logger = LoggerFactory.getLogger(TnAllocateNssi.class)
58
59     void preProcessRequest(DelegateExecution execution) {
60         logger.debug("Start preProcessRequest")
61         execution.setVariable("prefix", Prefix)
62         String msg = ""
63
64         try {
65             execution.setVariable("startTime", System.currentTimeMillis())
66
67             msg = tnNssmfUtils.getExecutionInputParams(execution)
68             logger.debug("Allocate TN NSSI input parameters: " + msg)
69
70             tnNssmfUtils.setSdncCallbackUrl(execution, true)
71             logger.debug("SDNC Callback URL: " + execution.getVariable("sdncCallbackUrl"))
72
73             String additionalPropJsonStr = execution.getVariable("sliceParams")
74
75             String tnNssiId = jsonUtil.getJsonValue(additionalPropJsonStr, "serviceInstanceID") //for debug
76             if (isBlank(tnNssiId)) {
77                 tnNssiId = UUID.randomUUID().toString()
78             }
79
80             String operationId = UUID.randomUUID().toString()
81             execution.setVariable("operationId", operationId)
82
83             logger.debug("Generate new TN NSSI ID:" + tnNssiId)
84             tnNssiId = UriUtils.encode(tnNssiId, "UTF-8")
85             execution.setVariable("sliceServiceInstanceId", tnNssiId)
86
87             String sliceServiceInstanceName = execution.getVariable("servicename")
88             execution.setVariable("sliceServiceInstanceName", sliceServiceInstanceName)
89
90             String sst = execution.getVariable("sst")
91             execution.setVariable("sst", sst)
92
93             //additional properties
94             String sliceProfile = jsonUtil.getJsonValue(additionalPropJsonStr, "sliceProfile")
95             if (isBlank(sliceProfile)) {
96                 msg = "Input sliceProfile is null"
97                 logger.debug(msg)
98                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
99             } else {
100                 execution.setVariable("sliceProfile", sliceProfile)
101             }
102
103             String transportSliceNetworks = jsonUtil.getJsonValue(additionalPropJsonStr, "transportSliceNetworks")
104             if (isBlank(transportSliceNetworks)) {
105                 msg = "Input transportSliceNetworks is null"
106                 logger.debug(msg)
107                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
108             } else {
109                 execution.setVariable("transportSliceNetworks", transportSliceNetworks)
110             }
111             logger.debug("transportSliceNetworks: " + transportSliceNetworks)
112
113             String nsiInfoStr = jsonUtil.getJsonValue(additionalPropJsonStr, "nsiInfo")
114             if (isBlank(nsiInfoStr)) {
115                 msg = "Input nsiInfo is null"
116                 logger.debug(msg)
117                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
118             } else {
119                 execution.setVariable("nsiInfo", nsiInfoStr)
120             }
121
122             if (isBlank(tnNssmfUtils.setExecVarFromJsonIfExists(execution, additionalPropJsonStr,
123                     "enableSdnc", "enableSdnc"))) {
124                 tnNssmfUtils.setEnableSdncConfig(execution)
125             }
126         } catch (BpmnError e) {
127             throw e
128         } catch (Exception ex) {
129             msg = "Exception in preProcessRequest " + ex.getMessage()
130             logger.debug(msg)
131             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
132         }
133         logger.debug("Finish preProcessRequest")
134     }
135
136
137     void prepareDecomposeService(DelegateExecution execution) {
138         logger.debug("Start prepareDecomposeService")
139         String msg = ""
140         String modelUuid = execution.getVariable("modelUuid")
141         if (isBlank(modelUuid)) {
142             msg = "Input modelUuid is null"
143             logger.debug(msg)
144             exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
145         }
146
147         String modelInvariantUuid = execution.getVariable("modelInvariantUuid")
148         if (isBlank(modelInvariantUuid)) {
149             msg = "Input modelInvariantUuid is null"
150             logger.debug(msg)
151             exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
152         }
153
154         String serviceModelInfo = """{
155             "modelInvariantUuid":"${modelInvariantUuid}",
156             "modelUuid":"${modelUuid}",
157             "modelVersion":""
158              }"""
159         execution.setVariable("serviceModelInfo", serviceModelInfo)
160
161         logger.debug("Finish prepareDecomposeService")
162     }
163
164     void processDecomposition(DelegateExecution execution) {
165         logger.debug("Start processDecomposition")
166
167         ServiceDecomposition tnNsstServiceDecomposition = execution.getVariable("tnNsstServiceDecomposition")
168         logger.debug("tnNsstServiceDecomposition : " + tnNsstServiceDecomposition.toString())
169         //TN NSST decomposition
170         String tnModelVersion = tnNsstServiceDecomposition.getModelInfo().getModelVersion()
171         String tnModelName = tnNsstServiceDecomposition.getModelInfo().getModelName()
172         List<ServiceProxy> serviceProxyList = tnNsstServiceDecomposition.getServiceProxy()
173         List<String> nsstInfoList = new ArrayList<>()
174         for (ServiceProxy serviceProxy : serviceProxyList) {
175             String nsstModelUuid = serviceProxy.getModelInfo().getModelUuid()
176             String nsstModelInvariantUuid = serviceProxy.getModelInfo().getModelInvariantUuid()
177             String name = serviceProxy.getModelInfo().getModelName()
178             String nsstServiceModelInfo = """{
179             "UUID":"${nsstModelUuid}",
180             "invariantUUID":"${nsstModelInvariantUuid}",
181             "name":"${name}"
182              }"""
183             nsstInfoList.add(nsstServiceModelInfo)
184         }
185         int currentIndex = 0
186         int maxIndex = nsstInfoList.size()
187         if (maxIndex < 1) {
188             String msg = "Exception in TN NSST processDecomposition. There is no NSST associated with TN NSST "
189             logger.info(msg)
190             //exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
191         } else {
192             execution.setVariable("tnNsstInfoList", nsstInfoList)
193             execution.setVariable("tnModelVersion", tnModelVersion)
194             execution.setVariable("tnModelName", tnModelName)
195             execution.setVariable("currentIndex", currentIndex)
196             execution.setVariable("maxIndex", maxIndex)
197         }
198
199         logger.debug("End processDecomposition")
200     }
201
202     void prepareOofSelection(DelegateExecution execution) {
203         logger.debug("Start prepareOofSelection")
204
205         String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
206         logger.debug("get NSSI option OOF Url: " + urlString)
207         //build oof request body
208         String requestId = execution.getVariable("msoRequestId")
209         String messageType = "NSISelectionResponse"
210         Map<String, Object> profileInfo = objectMapper.readValue(execution.getVariable("sliceProfile"), Map.class)
211         String modelUuid = execution.getVariable("modelUuid")
212         String modelInvariantUuid = execution.getVariable("modelInvariantUuid")
213         String modelName = execution.getVariable("tnModelName")
214         String timeout = UrnPropertiesReader.getVariable("mso.adapters.oof.timeout", execution);
215         List<String> nsstInfoList = objectMapper.readValue(execution.getVariable("nsstInfoList"), List.class)
216         JsonArray capabilitiesList = new JsonArray()
217
218         execution.setVariable("nssiSelection_Url", "/api/oof/selection/nsi/v1")
219         execution.setVariable("nssiSelection_messageType", messageType)
220         execution.setVariable("nssiSelection_correlator", requestId)
221         execution.setVariable("nssiSelection_timeout", timeout)
222         String oofRequest = buildSelectTnNssiRequest(requestId, messageType, modelUuid, modelInvariantUuid,
223                 modelName, profileInfo, nsstInfoList, capabilitiesList, false)
224         execution.setVariable("nssiSelection_oofRequest", oofRequest)
225
226         logger.debug("Finish prepareOofSelection")
227     }
228
229     String buildSelectTnNssiRequest(String requestId, String messageType, String UUID, String invariantUUID,
230                                     String name, Map<String, Object> profileInfo,
231                                     List<String> nsstInfoList, JsonArray capabilitiesList, Boolean preferReuse) {
232
233         def transactionId = requestId
234         logger.debug("transactionId is: " + transactionId)
235         String correlator = requestId
236         String callbackUrl = UrnPropertiesReader.getVariable("mso.adapters.oof.callback.endpoint") + "/" + messageType + "/" + correlator
237         ObjectMapper objectMapper = new ObjectMapper()
238         String profileJson = objectMapper.writeValueAsString(profileInfo)
239         String nsstInfoListString = objectMapper.writeValueAsString(nsstInfoList)
240         //Prepare requestInfo object
241         JsonObject requestInfo = new JsonObject()
242         requestInfo.addProperty("transactionId", transactionId)
243         requestInfo.addProperty("requestId", requestId)
244         requestInfo.addProperty("callbackUrl", callbackUrl)
245         requestInfo.addProperty("sourceId", "SO")
246         requestInfo.addProperty("timeout", 600)
247         requestInfo.addProperty("numSolutions", 1)
248
249         //Prepare serviceInfo object
250         JsonObject ranNsstInfo = new JsonObject()
251         ranNsstInfo.addProperty("UUID", UUID)
252         ranNsstInfo.addProperty("invariantUUID", invariantUUID)
253         ranNsstInfo.addProperty("name", name)
254
255         JsonObject json = new JsonObject()
256         json.add("requestInfo", requestInfo)
257         json.add("NSTInfo", ranNsstInfo)
258         json.addProperty("serviceProfile", profileJson)
259         json.addProperty("NSSTInfo", nsstInfoListString)
260         json.add("subnetCapabilities", capabilitiesList)
261         json.addProperty("preferReuse", preferReuse)
262
263         return json.toString()
264     }
265
266     void processOofSelection(DelegateExecution execution) {
267         logger.debug(Prefix + "processOofSelection method start")
268         String oofResponse = execution.getVariable("nssiSelection_asyncCallbackResponse")
269         String requestStatus = jsonUtil.getJsonValue(oofResponse, "requestStatus")
270         if (requestStatus.equals("completed")) {
271             List<String> solution = jsonUtil.StringArrayToList(jsonUtil.getJsonValue(oofResponse, "solutions"))
272             boolean existingNSI = jsonUtil.getJsonValue(solution.get(0), "existingNSI")
273             if (existingNSI) {
274                 def sharedNSISolution = jsonUtil.getJsonValue(solution.get(0), "sharedNSISolution")
275                 execution.setVariable("sharedTnNssiSolution", sharedNSISolution)
276                 logger.debug("sharedTnNssiSolution from OOF " + sharedNSISolution)
277                 String tnServiceInstanceId = jsonUtil.getJsonValue(solution.get(0), "sharedNSISolution.NSIId")
278                 execution.setVariable("tnServiceInstanceId", tnServiceInstanceId)
279                 org.onap.so.bpmn.core.domain.ServiceInstance serviceInstance = new org.onap.so.bpmn.core.domain.ServiceInstance();
280                 serviceInstance.setInstanceId(tnServiceInstanceId);
281                 ServiceDecomposition serviceDecomposition = execution.getVariable("tnNsstServiceDecomposition")
282                 serviceDecomposition.setServiceInstance(serviceInstance);
283                 execution.setVariable("tnNsstServiceDecomposition", serviceDecomposition)
284                 execution.setVariable("isOofTnNssiSelected", true)
285             } else {
286                 def sliceProfiles = jsonUtil.getJsonValue(solution.get(0), "newNSISolution.sliceProfiles")
287                 execution.setVariable("tnConstituentSliceProfiles", sliceProfiles)
288                 execution.setVariable("isOofTnNssiSelected", false)
289                 logger.debug("tnConstituentSliceProfiles list from OOF " + sliceProfiles)
290             }
291         } else {
292             String statusMessage = jsonUtil.getJsonValue(oofResponse, "statusMessage")
293             logger.error("received failed status from oof " + statusMessage)
294             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Received a failed Async Response from OOF : " + statusMessage)
295         }
296
297         logger.debug(Prefix + "processOofSelection method finished")
298     }
299
300     void updateAAIOrchStatus(DelegateExecution execution) {
301         logger.debug("Start updateAAIOrchStatus")
302         String sliceServiceInstanceId = execution.getVariable("sliceServiceInstanceId")
303         String orchStatus = execution.getVariable("orchestrationStatus")
304
305         try {
306             ServiceInstance si = new ServiceInstance()
307             si.setOrchestrationStatus(orchStatus)
308             AAIResourcesClient client = new AAIResourcesClient()
309             AAIResourceUri uri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(sliceServiceInstanceId))
310             client.update(uri, si)
311         } catch (BpmnError e) {
312             throw e
313         } catch (Exception ex) {
314             String msg = "Exception in CreateSliceService.updateAAIOrchStatus " + ex.getMessage()
315             logger.info(msg)
316             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
317         }
318
319         logger.debug("Finish updateAAIOrchStatus")
320     }
321
322
323     void prepareUpdateJobStatus(DelegateExecution execution,
324                                 String status,
325                                 String progress,
326                                 String statusDescription) {
327         String modelUuid = execution.getVariable("modelUuid")
328         String ssInstanceId = execution.getVariable("sliceServiceInstanceId")
329         String jobId = execution.getVariable("jobId")
330         String nsiId = execution.getVariable("nsiId")
331
332         ResourceOperationStatus roStatus = new ResourceOperationStatus()
333         roStatus.setServiceId(nsiId)
334         roStatus.setOperationId(jobId)
335         roStatus.setResourceTemplateUUID(modelUuid)
336         roStatus.setResourceInstanceID(ssInstanceId)
337         roStatus.setOperType("ALLOCATE")
338         roStatus.setProgress(progress)
339         roStatus.setStatus(status)
340         roStatus.setStatusDescription(statusDescription)
341         requestDBUtil.prepareUpdateResourceOperationStatus(execution, roStatus)
342     }
343
344 }
345