Merge "bump the so version to 1.7.4"
[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 = execution.getVariable("serviceInstanceID")
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             //additional properties
91             String sliceProfile = jsonUtil.getJsonValue(additionalPropJsonStr, "sliceProfile")
92             if (isBlank(sliceProfile)) {
93                 msg = "Input sliceProfile is null"
94                 logger.debug(msg)
95                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
96             } else {
97                 execution.setVariable("sliceProfile", sliceProfile)
98             }
99
100             String transportSliceNetworks = jsonUtil.getJsonValue(additionalPropJsonStr, "transportSliceNetworks")
101             if (isBlank(transportSliceNetworks)) {
102                 msg = "Input transportSliceNetworks is null"
103                 logger.debug(msg)
104                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
105             } else {
106                 execution.setVariable("transportSliceNetworks", transportSliceNetworks)
107             }
108             logger.debug("transportSliceNetworks: " + transportSliceNetworks)
109
110             String nsiInfoStr = jsonUtil.getJsonValue(additionalPropJsonStr, "nsiInfo")
111             if (isBlank(nsiInfoStr)) {
112                 msg = "Input nsiInfo is null"
113                 logger.debug(msg)
114                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
115             } else {
116                 execution.setVariable("nsiInfo", nsiInfoStr)
117             }
118
119             //nsiId is passed in from caller bpmn
120             //String nsiIdStr = jsonUtil.getJsonValue(nsiInfo, "nsiId")
121             //execution.setVariable("nsiId", nsiIdStr)
122
123         } catch (BpmnError e) {
124             throw e
125         } catch (Exception ex) {
126             msg = "Exception in preProcessRequest " + ex.getMessage()
127             logger.debug(msg)
128             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
129         }
130         logger.debug("Finish preProcessRequest")
131     }
132
133
134     void prepareDecomposeService(DelegateExecution execution) {
135         logger.debug("Start prepareDecomposeService")
136         String msg = ""
137         String modelUuid = execution.getVariable("modelUuid")
138         if (isBlank(modelUuid)) {
139             msg = "Input modelUuid is null"
140             logger.debug(msg)
141             exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
142         }
143
144         String modelInvariantUuid = execution.getVariable("modelInvariantUuid")
145         if (isBlank(modelInvariantUuid)) {
146             msg = "Input modelInvariantUuid is null"
147             logger.debug(msg)
148             exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
149         }
150
151         String serviceModelInfo = """{
152             "modelInvariantUuid":"${modelInvariantUuid}",
153             "modelUuid":"${modelUuid}",
154             "modelVersion":""
155              }"""
156         execution.setVariable("serviceModelInfo", serviceModelInfo)
157
158         logger.debug("Finish prepareDecomposeService")
159     }
160
161     void processDecomposition(DelegateExecution execution) {
162         logger.debug("Start processDecomposition")
163
164         ServiceDecomposition tnNsstServiceDecomposition = execution.getVariable("tnNsstServiceDecomposition")
165         logger.debug("tnNsstServiceDecomposition : " + tnNsstServiceDecomposition.toString())
166         //TN NSST decomposition
167         String tnModelVersion = tnNsstServiceDecomposition.getModelInfo().getModelVersion()
168         String tnModelName = tnNsstServiceDecomposition.getModelInfo().getModelName()
169         List<ServiceProxy> serviceProxyList = tnNsstServiceDecomposition.getServiceProxy()
170         List<String> nsstInfoList = new ArrayList<>()
171         for (ServiceProxy serviceProxy : serviceProxyList) {
172             String nsstModelUuid = serviceProxy.getModelInfo().getModelUuid()
173             String nsstModelInvariantUuid = serviceProxy.getModelInfo().getModelInvariantUuid()
174             String name = serviceProxy.getModelInfo().getModelName()
175             String nsstServiceModelInfo = """{
176             "UUID":"${nsstModelUuid}",
177             "invariantUUID":"${nsstModelInvariantUuid}",
178             "name":"${name}"
179              }"""
180             nsstInfoList.add(nsstServiceModelInfo)
181         }
182         int currentIndex = 0
183         int maxIndex = nsstInfoList.size()
184         if (maxIndex < 1) {
185             String msg = "Exception in TN NSST processDecomposition. There is no NSST associated with TN NSST "
186             logger.info(msg)
187             //exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
188         } else {
189             execution.setVariable("tnNsstInfoList", nsstInfoList)
190             execution.setVariable("tnModelVersion", tnModelVersion)
191             execution.setVariable("tnModelName", tnModelName)
192             execution.setVariable("currentIndex", currentIndex)
193             execution.setVariable("maxIndex", maxIndex)
194         }
195
196         logger.debug("End processDecomposition")
197     }
198
199     void prepareOofSelection(DelegateExecution execution) {
200         logger.debug("Start prepareOofSelection")
201
202         String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
203         logger.debug("get NSSI option OOF Url: " + urlString)
204         //build oof request body
205         String requestId = execution.getVariable("msoRequestId")
206         String messageType = "NSISelectionResponse"
207         Map<String, Object> profileInfo = objectMapper.readValue(execution.getVariable("sliceProfile"), Map.class)
208         String modelUuid = execution.getVariable("modelUuid")
209         String modelInvariantUuid = execution.getVariable("modelInvariantUuid")
210         String modelName = execution.getVariable("tnModelName")
211         String timeout = UrnPropertiesReader.getVariable("mso.adapters.oof.timeout", execution);
212         List<String> nsstInfoList = objectMapper.readValue(execution.getVariable("nsstInfoList"), List.class)
213         JsonArray capabilitiesList = new JsonArray()
214
215         execution.setVariable("nssiSelection_Url", "/api/oof/selection/nsi/v1")
216         execution.setVariable("nssiSelection_messageType", messageType)
217         execution.setVariable("nssiSelection_correlator", requestId)
218         execution.setVariable("nssiSelection_timeout", timeout)
219         String oofRequest = buildSelectTnNssiRequest(requestId, messageType, modelUuid, modelInvariantUuid,
220                 modelName, profileInfo, nsstInfoList, capabilitiesList, false)
221         execution.setVariable("nssiSelection_oofRequest", oofRequest)
222
223         logger.debug("Finish prepareOofSelection")
224     }
225
226     String buildSelectTnNssiRequest(String requestId, String messageType, String UUID, String invariantUUID,
227                                     String name, Map<String, Object> profileInfo,
228                                     List<String> nsstInfoList, JsonArray capabilitiesList, Boolean preferReuse) {
229
230         def transactionId = requestId
231         logger.debug("transactionId is: " + transactionId)
232         String correlator = requestId
233         String callbackUrl = UrnPropertiesReader.getVariable("mso.adapters.oof.callback.endpoint") + "/" + messageType + "/" + correlator
234         ObjectMapper objectMapper = new ObjectMapper()
235         String profileJson = objectMapper.writeValueAsString(profileInfo)
236         String nsstInfoListString = objectMapper.writeValueAsString(nsstInfoList)
237         //Prepare requestInfo object
238         JsonObject requestInfo = new JsonObject()
239         requestInfo.addProperty("transactionId", transactionId)
240         requestInfo.addProperty("requestId", requestId)
241         requestInfo.addProperty("callbackUrl", callbackUrl)
242         requestInfo.addProperty("sourceId", "SO")
243         requestInfo.addProperty("timeout", 600)
244         requestInfo.addProperty("numSolutions", 1)
245
246         //Prepare serviceInfo object
247         JsonObject ranNsstInfo = new JsonObject()
248         ranNsstInfo.addProperty("UUID", UUID)
249         ranNsstInfo.addProperty("invariantUUID", invariantUUID)
250         ranNsstInfo.addProperty("name", name)
251
252         JsonObject json = new JsonObject()
253         json.add("requestInfo", requestInfo)
254         json.add("NSTInfo", ranNsstInfo)
255         json.addProperty("serviceProfile", profileJson)
256         json.addProperty("NSSTInfo", nsstInfoListString)
257         json.add("subnetCapabilities", capabilitiesList)
258         json.addProperty("preferReuse", preferReuse)
259
260         return json.toString()
261     }
262
263     void processOofSelection(DelegateExecution execution) {
264         logger.debug(Prefix + "processOofSelection method start")
265         String oofResponse = execution.getVariable("nssiSelection_asyncCallbackResponse")
266         String requestStatus = jsonUtil.getJsonValue(oofResponse, "requestStatus")
267         if (requestStatus.equals("completed")) {
268             List<String> solution = jsonUtil.StringArrayToList(jsonUtil.getJsonValue(oofResponse, "solutions"))
269             boolean existingNSI = jsonUtil.getJsonValue(solution.get(0), "existingNSI")
270             if (existingNSI) {
271                 def sharedNSISolution = jsonUtil.getJsonValue(solution.get(0), "sharedNSISolution")
272                 execution.setVariable("sharedTnNssiSolution", sharedNSISolution)
273                 logger.debug("sharedTnNssiSolution from OOF " + sharedNSISolution)
274                 String tnServiceInstanceId = jsonUtil.getJsonValue(solution.get(0), "sharedNSISolution.NSIId")
275                 execution.setVariable("tnServiceInstanceId", tnServiceInstanceId)
276                 org.onap.so.bpmn.core.domain.ServiceInstance serviceInstance = new org.onap.so.bpmn.core.domain.ServiceInstance();
277                 serviceInstance.setInstanceId(tnServiceInstanceId);
278                 ServiceDecomposition serviceDecomposition = execution.getVariable("tnNsstServiceDecomposition")
279                 serviceDecomposition.setServiceInstance(serviceInstance);
280                 execution.setVariable("tnNsstServiceDecomposition", serviceDecomposition)
281                 execution.setVariable("isOofTnNssiSelected", true)
282             } else {
283                 def sliceProfiles = jsonUtil.getJsonValue(solution.get(0), "newNSISolution.sliceProfiles")
284                 execution.setVariable("tnConstituentSliceProfiles", sliceProfiles)
285                 execution.setVariable("isOofTnNssiSelected", false)
286                 logger.debug("tnConstituentSliceProfiles list from OOF " + sliceProfiles)
287             }
288         } else {
289             String statusMessage = jsonUtil.getJsonValue(oofResponse, "statusMessage")
290             logger.error("received failed status from oof " + statusMessage)
291             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Received a failed Async Response from OOF : " + statusMessage)
292         }
293
294         logger.debug(Prefix + "processOofSelection method finished")
295     }
296
297     void updateAAIOrchStatus(DelegateExecution execution) {
298         logger.debug("Start updateAAIOrchStatus")
299         String sliceServiceInstanceId = execution.getVariable("sliceServiceInstanceId")
300         String orchStatus = execution.getVariable("orchestrationStatus")
301
302         try {
303             ServiceInstance si = new ServiceInstance()
304             si.setOrchestrationStatus(orchStatus)
305             AAIResourcesClient client = new AAIResourcesClient()
306             AAIResourceUri uri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(sliceServiceInstanceId))
307             client.update(uri, si)
308         } catch (BpmnError e) {
309             throw e
310         } catch (Exception ex) {
311             String msg = "Exception in CreateSliceService.updateAAIOrchStatus " + ex.getMessage()
312             logger.info(msg)
313             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
314         }
315
316         logger.debug("Finish updateAAIOrchStatus")
317     }
318
319
320     void prepareUpdateJobStatus(DelegateExecution execution,
321                                 String status,
322                                 String progress,
323                                 String statusDescription) {
324         String serviceId = execution.getVariable("sliceServiceInstanceId")
325         String jobId = execution.getVariable("jobId")
326         String nsiId = execution.getVariable("nsiId")
327
328         ResourceOperationStatus roStatus = new ResourceOperationStatus()
329         roStatus.setServiceId(serviceId)
330         roStatus.setOperationId(jobId)
331         roStatus.setResourceTemplateUUID(nsiId)
332         roStatus.setOperType("Allocate")
333         roStatus.setProgress(progress)
334         roStatus.setStatus(status)
335         roStatus.setStatusDescription(statusDescription)
336         requestDBUtil.prepareUpdateResourceOperationStatus(execution, roStatus)
337     }
338
339 }
340