Merge "Implementation of TN NSSMF WF on SO"
[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.AAIObjectType
31 import org.onap.aaiclient.client.aai.AAIResourcesClient
32 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
33 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
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("ssServiceModelInfo", 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         }
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         logger.debug("End processDecomposition")
196     }
197
198     void prepareOofSelection(DelegateExecution execution) {
199         logger.debug("Start prepareOofSelection")
200
201         String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
202         logger.debug("get NSSI option OOF Url: " + urlString)
203         //build oof request body
204         String requestId = execution.getVariable("msoRequestId")
205         String messageType = "NSISelectionResponse"
206         Map<String, Object> profileInfo = objectMapper.readValue(execution.getVariable("sliceProfile"), Map.class)
207         String modelUuid = execution.getVariable("modelUuid")
208         String modelInvariantUuid = execution.getVariable("modelInvariantUuid")
209         String modelName = execution.getVariable("tnModelName")
210         String timeout = UrnPropertiesReader.getVariable("mso.adapters.oof.timeout", execution);
211         List<String> nsstInfoList = objectMapper.readValue(execution.getVariable("nsstInfoList"), List.class)
212         JsonArray capabilitiesList = new JsonArray()
213
214         execution.setVariable("nssiSelection_Url", "/api/oof/selection/nsi/v1")
215         execution.setVariable("nssiSelection_messageType", messageType)
216         execution.setVariable("nssiSelection_correlator", requestId)
217         execution.setVariable("nssiSelection_timeout", timeout)
218         String oofRequest = buildSelectTnNssiRequest(requestId, messageType, modelUuid, modelInvariantUuid,
219                 modelName, profileInfo, nsstInfoList, capabilitiesList, false)
220         execution.setVariable("nssiSelection_oofRequest", oofRequest)
221
222         logger.debug("Finish prepareOofSelection")
223     }
224
225     String buildSelectTnNssiRequest(String requestId, String messageType, String UUID, String invariantUUID,
226                                     String name, Map<String, Object> profileInfo,
227                                     List<String> nsstInfoList, JsonArray capabilitiesList, Boolean preferReuse) {
228
229         def transactionId = requestId
230         logger.debug("transactionId is: " + transactionId)
231         String correlator = requestId
232         String callbackUrl = UrnPropertiesReader.getVariable("mso.adapters.oof.callback.endpoint") + "/" + messageType + "/" + correlator
233         ObjectMapper objectMapper = new ObjectMapper()
234         String profileJson = objectMapper.writeValueAsString(profileInfo)
235         String nsstInfoListString = objectMapper.writeValueAsString(nsstInfoList)
236         //Prepare requestInfo object
237         JsonObject requestInfo = new JsonObject()
238         requestInfo.addProperty("transactionId", transactionId)
239         requestInfo.addProperty("requestId", requestId)
240         requestInfo.addProperty("callbackUrl", callbackUrl)
241         requestInfo.addProperty("sourceId", "SO")
242         requestInfo.addProperty("timeout", 600)
243         requestInfo.addProperty("numSolutions", 1)
244
245         //Prepare serviceInfo object
246         JsonObject ranNsstInfo = new JsonObject()
247         ranNsstInfo.addProperty("UUID", UUID)
248         ranNsstInfo.addProperty("invariantUUID", invariantUUID)
249         ranNsstInfo.addProperty("name", name)
250
251         JsonObject json = new JsonObject()
252         json.add("requestInfo", requestInfo)
253         json.add("NSTInfo", ranNsstInfo)
254         json.addProperty("serviceProfile", profileJson)
255         json.addProperty("NSSTInfo", nsstInfoListString)
256         json.add("subnetCapabilities", capabilitiesList)
257         json.addProperty("preferReuse", preferReuse)
258
259         return json.toString()
260     }
261
262     void processOofSelection(DelegateExecution execution) {
263         logger.debug(Prefix + "processOofSelection method start")
264         String oofResponse = execution.getVariable("nssiSelection_asyncCallbackResponse")
265         String requestStatus = jsonUtil.getJsonValue(oofResponse, "requestStatus")
266         if (requestStatus.equals("completed")) {
267             List<String> solution = jsonUtil.StringArrayToList(jsonUtil.getJsonValue(oofResponse, "solutions"))
268             boolean existingNSI = jsonUtil.getJsonValue(solution.get(0), "existingNSI")
269             if (existingNSI) {
270                 def sharedNSISolution = jsonUtil.getJsonValue(solution.get(0), "sharedNSISolution")
271                 execution.setVariable("sharedTnNssiSolution", sharedNSISolution)
272                 logger.debug("sharedTnNssiSolution from OOF " + sharedNSISolution)
273                 String tnServiceInstanceId = jsonUtil.getJsonValue(solution.get(0), "sharedNSISolution.NSIId")
274                 execution.setVariable("tnServiceInstanceId", tnServiceInstanceId)
275                 org.onap.so.bpmn.core.domain.ServiceInstance serviceInstance = new org.onap.so.bpmn.core.domain.ServiceInstance();
276                 serviceInstance.setInstanceId(tnServiceInstanceId);
277                 ServiceDecomposition serviceDecomposition = execution.getVariable("tnNsstServiceDecomposition")
278                 serviceDecomposition.setServiceInstance(serviceInstance);
279                 execution.setVariable("tnNsstServiceDecomposition", serviceDecomposition)
280                 execution.setVariable("isOofTnNssiSelected", true)
281             } else {
282                 def sliceProfiles = jsonUtil.getJsonValue(solution.get(0), "newNSISolution.sliceProfiles")
283                 execution.setVariable("tnConstituentSliceProfiles", sliceProfiles)
284                 execution.setVariable("isOofTnNssiSelected", false)
285                 logger.debug("tnConstituentSliceProfiles list from OOF " + sliceProfiles)
286             }
287         } else {
288             String statusMessage = jsonUtil.getJsonValue(oofResponse, "statusMessage")
289             logger.error("received failed status from oof " + statusMessage)
290             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, "Received a failed Async Response from OOF : " + statusMessage)
291         }
292
293         logger.debug(Prefix + "processOofSelection method finished")
294     }
295
296     void updateAAIOrchStatus(DelegateExecution execution) {
297         logger.debug("Start updateAAIOrchStatus")
298         String sliceServiceInstanceId = execution.getVariable("sliceServiceInstanceId")
299         String orchStatus = execution.getVariable("orchestrationStatus")
300
301         try {
302             ServiceInstance si = new ServiceInstance()
303             si.setOrchestrationStatus(orchStatus)
304             AAIResourcesClient client = new AAIResourcesClient()
305             AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, sliceServiceInstanceId)
306             client.update(uri, si)
307         } catch (BpmnError e) {
308             throw e
309         } catch (Exception ex) {
310             String msg = "Exception in CreateSliceService.updateAAIOrchStatus " + ex.getMessage()
311             logger.info(msg)
312             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
313         }
314
315         logger.debug("Finish updateAAIOrchStatus")
316     }
317
318
319     void prepareUpdateJobStatus(DelegateExecution execution,
320                                 String status,
321                                 String progress,
322                                 String statusDescription) {
323         String serviceId = execution.getVariable("sliceServiceInstanceId")
324         String jobId = execution.getVariable("jobId")
325         String nsiId = execution.getVariable("nsiId")
326
327         ResourceOperationStatus roStatus = new ResourceOperationStatus()
328         roStatus.setServiceId(serviceId)
329         roStatus.setOperationId(jobId)
330         roStatus.setResourceTemplateUUID(nsiId)
331         roStatus.setOperType("Allocate")
332         roStatus.setProgress(progress)
333         roStatus.setStatus(status)
334         roStatus.setStatusDescription(statusDescription)
335         requestDBUtil.prepareUpdateResourceOperationStatus(execution, status)
336     }
337
338 }
339