Containerization feature of SO
[so.git] / bpmn / MSOCommonBPMN / src / main / groovy / org / onap / so / bpmn / common / scripts / SniroUtils.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. 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.common.scripts
22
23 import org.camunda.bpm.engine.delegate.BpmnError
24 import org.camunda.bpm.engine.delegate.DelegateExecution
25 import org.json.JSONArray
26 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
27 import org.onap.so.bpmn.common.scripts.ExceptionUtil
28 import org.onap.so.bpmn.common.scripts.MsoUtils
29 import org.onap.so.bpmn.core.domain.*
30 import org.onap.so.bpmn.core.json.JsonUtils
31 import org.apache.commons.lang3.StringUtils
32
33 import static  org.onap.so.bpmn.common.scripts.GenericUtils.*
34
35 import java.time.Duration
36
37 import org.onap.so.logger.MessageEnum
38 import org.onap.so.logger.MsoLogger
39
40
41
42 class SniroUtils{
43         private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, SniroUtils.class);
44
45
46         ExceptionUtil exceptionUtil = new ExceptionUtil()
47         JsonUtils jsonUtil = new JsonUtils()
48
49         private AbstractServiceTaskProcessor utils
50
51         public MsoUtils msoUtils = new MsoUtils()
52
53         public SniroUtils(AbstractServiceTaskProcessor taskProcessor) {
54                 this.utils = taskProcessor
55         }
56
57         /**
58          * This method builds the service-agnostic
59          * sniro json request to get a homing solution
60          * and license solution
61          *
62          * @param execution
63          * @param requestId
64          * @param decomposition - ServiceDecomposition object
65          * @param subscriber - Subscriber information
66          * @param homingParams - Homing/Request parameters
67          *
68          * @return request - sniro v2 payload
69          *
70          * @author cb645j
71          */
72         public String buildRequest(DelegateExecution execution, String requestId, ServiceDecomposition decomposition, Subscriber subscriber, String homingParams){
73                 msoLogger.debug("Started Building Sniro Request")
74                 def callbackUrl = utils.createWorkflowMessageAdapterCallbackURL(execution, "SNIROResponse", requestId)
75                 def transactionId = requestId
76                 //ServiceInstance Info
77                 ServiceInstance serviceInstance = decomposition.getServiceInstance()
78                 def serviceInstanceId
79                 if(serviceInstance == null){
80                         msoLogger.debug("Unable to obtain Service Instance Id, ServiceInstance Object is null" )
81                         exceptionUtil.buildAndThrowWorkflowException(execution, 400, "Internal Error - Unable to obtain Service Instance Id, ServiceInstance Object is null")
82                 }else{
83                         serviceInstanceId = serviceInstance.getInstanceId()
84                 }
85                 String type = decomposition.getServiceType()
86                 String serviceType = ""
87                 if(isNotBlank(type)){
88                         serviceType = """ "serviceType": "${type}", """
89                 }
90                 //Model Info
91                 ModelInfo model = decomposition.getModelInfo()
92                 String modelType = model.getModelType()
93                 String modelInvariantId = model.getModelInvariantUuid()
94                 String modelVersionId = model.getModelUuid()
95                 String modelName = model.getModelName()
96                 String modelVersion = model.getModelVersion()
97                 //Subscriber Info
98                 String subscriberId = subscriber.getGlobalId()
99                 String subscriberName = subscriber.getName()
100                 String commonSiteId = subscriber.getCommonSiteId()
101                 //OrderInfo
102                 String orderInfo
103                 if(!isBlank(homingParams)){
104                         orderInfo = homingParams.replaceAll("\"", "\\\\\"").replaceAll("\n", "").replaceAll("\r", "")
105                         orderInfo = StringUtils.normalizeSpace(orderInfo)
106                 }
107
108                 //Determine RequestType
109                 //TODO Implement better way to determine this
110                 String requestType = "initial"
111                 List<Resource> resources = decomposition.getServiceResources()
112                 for(Resource r:resources){
113                         HomingSolution currentSolution = (HomingSolution) r.getCurrentHomingSolution()
114                         if(currentSolution != null){
115                                 requestType = "speed changed"
116                         }
117                 }
118
119                 String timeout = execution.getVariable("timeout")
120                 Duration d = Duration.parse(timeout);
121                 long timeoutSeconds = d.getSeconds();
122
123                 //Demands
124                 String placementDemands = ""
125                 StringBuilder sb = new StringBuilder()
126                 List<Resource> resourceList = decomposition.getAllottedResources()
127                 List<VnfResource> vnfResourceList = decomposition.getVnfResources()
128
129                 //TODO should be service agnostic so this is just a temp solution to all vnfs to be sent in placement container for adiod
130                 if(resourceList.isEmpty() || resourceList == null){
131                         search : {
132                                 for(VnfResource vnf : vnfResourceList){
133                                         if(StringUtils.containsIgnoreCase(vnf.getNfRole(), "vce") || StringUtils.containsIgnoreCase(vnf.getNfRole(), "vpe")){
134                                                 resourceList = decomposition.getVnfResources()
135                                                 break search
136                                         }
137                                 }
138                         }
139                 }
140
141                 if(resourceList.isEmpty() || resourceList == null){
142                         msoLogger.debug("Resources List is Empty")
143                 }else{
144                         for(Resource resource:resourceList){
145                                 ModelInfo resourceModelInfo = resource.getModelInfo()
146                                 ResourceInstance resourceInstance = resource.getResourceInstance()
147                                 def resourceInstanceType = resource.getResourceType()
148                                 def serviceResourceId = resource.getResourceId() //TODO - resourceId versus instanceId - should be what is put in AAI, whatever we put here will be what is in response, used to correlate
149                                 def resourceModuleName = resourceModelInfo.getModelInstanceName()
150                                 def resouceModelCustomizationId = resourceModelInfo.getModelCustomizationUuid()
151                                 def resouceModelInvariantId = resourceModelInfo.getModelInvariantUuid()
152                                 def resouceModelName = resourceModelInfo.getModelName()
153                                 def resouceModelVersion = resourceModelInfo.getModelVersion()
154                                 def resouceModelVersionId = resourceModelInfo.getModelUuid()
155                                 def resouceModelType = resourceModelInfo.getModelType()
156                                 def tenantId = "" //Optional
157                                 def tenantName = "" //Optional
158
159
160                                 String existingPlacement = ""
161                                 HomingSolution currentPlacement = resource.getCurrentHomingSolution()
162                                 if(currentPlacement != null){
163                                         String homedServiceInstanceId = currentPlacement.getServiceInstanceId()
164                                         existingPlacement =
165                                         ""","existingPlacement": {
166                            "serviceInstanceId": "${homedServiceInstanceId}"
167                     }"""
168                                 }
169
170
171                                 String demand =
172                                         """{
173                                                 "resourceInstanceType": "${resourceInstanceType}",
174                                                 "serviceResourceId": "${serviceResourceId}",
175                                                 "resourceModuleName": "${resourceModuleName}",
176                                                 "resourceModelInfo": {
177                                                         "modelCustomizationId": "${resouceModelCustomizationId}",
178                                                         "modelInvariantId": "${resouceModelInvariantId}",
179                                                         "modelName": "${resouceModelName}",
180                                                         "modelVersion": "${resouceModelVersion}",
181                                                         "modelVersionId": "${resouceModelVersionId}",
182                                                         "modelType": "${resouceModelType}"
183                                                 },
184                                                 "tenantId": "${tenantId}",
185                                                 "tenantName": "${tenantName}"
186                                                 ${existingPlacement}
187                                         },"""
188
189                                 placementDemands = sb.append(demand)
190                         }
191                         placementDemands = placementDemands.substring(0, placementDemands.length() - 1);
192                 }
193
194                 String licenseDemands = ""
195                 sb = new StringBuilder()
196                 if(vnfResourceList.isEmpty() || vnfResourceList == null){
197                         msoLogger.debug("Vnf Resources List is Empty")
198                 }else{
199                         for(VnfResource vnfResource:vnfResourceList){
200                                 ModelInfo vnfResourceModelInfo = vnfResource.getModelInfo()
201                                 ResourceInstance vnfResourceInstance = vnfResource.getResourceInstance()
202                                 def resourceInstanceType = vnfResource.getResourceType()
203                                 def serviceResourceId = vnfResource.getResourceId()
204                                 def resourceModuleName = vnfResourceModelInfo.getModelInstanceName()
205                                 def resouceModelCustomizationId = vnfResourceModelInfo.getModelCustomizationUuid()
206                                 def resouceModelInvariantId = vnfResourceModelInfo.getModelInvariantUuid()
207                                 def resouceModelName = vnfResourceModelInfo.getModelName()
208                                 def resouceModelVersion = vnfResourceModelInfo.getModelVersion()
209                                 def resouceModelVersionId = vnfResourceModelInfo.getModelUuid()
210                                 def resouceModelType = vnfResourceModelInfo.getModelType()
211
212                                 String curentLicenseJson = ""
213                                 HomingSolution currentSol = vnfResource.getCurrentHomingSolution()
214                                 if(currentSol != null){
215                                         JSONArray entitlementPoolList = currentSol.getLicense().getEntitlementPoolListAsString()
216                                         JSONArray licenseKeyGroupList = currentSol.getLicense().getLicenseKeyGroupListAsString()
217                                         curentLicenseJson =
218                                         """ ,"existingLicense": {
219                                  "entitlementPoolUUID":
220                                                                         ${entitlementPoolList},
221                                  "licenseKeyGroupUUID":
222                                                                         ${licenseKeyGroupList}
223
224                            }"""
225                                 }
226
227                                 String demand =
228                                 """{
229                                                 "resourceInstanceType": "${resourceInstanceType}",
230                                                 "serviceResourceId": "${serviceResourceId}",
231                                                 "resourceModuleName": "${resourceModuleName}",
232                                                 "resourceModelInfo": {
233                                                         "modelCustomizationId": "${resouceModelCustomizationId}",
234                                                         "modelInvariantId": "${resouceModelInvariantId}",
235                                                         "modelName": "${resouceModelName}",
236                                                         "modelVersion": "${resouceModelVersion}",
237                                                         "modelVersionId": "${resouceModelVersionId}",
238                                                         "modelType": "${resouceModelType}"
239                                                 }
240                                                 ${curentLicenseJson}
241                                         },"""
242
243                                         licenseDemands = sb.append(demand)
244                         }
245                         licenseDemands = licenseDemands.substring(0, licenseDemands.length() - 1);
246                 }
247
248                 String request =
249                                 """{
250                 "requestInfo": {
251                                 "transactionId": "${transactionId}",
252                                 "requestId": "${requestId}",
253                                 "callbackUrl": "${callbackUrl}",
254                                 "sourceId": "mso",
255                                 "requestType": "${requestType}",
256                                 "optimizer": [
257                                         "placement",
258                                         "license"
259                                 ],
260                                 "numSolutions": 1,
261                                 "timeout": ${timeoutSeconds}
262                                 },
263                 "placementInfo": {
264                         ${serviceType}
265                         "serviceModelInfo": {
266                                 "modelType": "${modelType}",
267                                 "modelInvariantId": "${modelInvariantId}",
268                                 "modelVersionId": "${modelVersionId}",
269                                 "modelName": "${modelName}",
270                                 "modelVersion": "${modelVersion}"
271                                 },
272                         "subscriberInfo": {
273                                 "globalSubscriberId": "${subscriberId}",
274                                 "subscriberName": "${subscriberName}",
275                                 "subscriberCommonSiteId": "${commonSiteId}"
276                                 },
277                         "demandInfo": {
278                                 "placementDemand": [
279                                         ${placementDemands}
280                                 ],
281                                 "licenseDemand": [
282                                         ${licenseDemands}
283                                 ]
284                         },
285                         "policyId": [],
286                         "serviceInstanceId": "${serviceInstanceId}",
287                         "orderInfo": "{\\\"requestParameters\\\": ${orderInfo}}"
288                 }
289           }"""
290
291                 msoLogger.debug("Completed Building Sniro Request")
292                 return request
293         }
294
295         /**
296          * This method validates the async callback response from Sniro.
297          * If the response contains an exception the method will build
298          * and throw a workflow exception.
299          *
300          * @param execution
301          * @param response - sniro async response
302          *
303          * @author cb645j
304          */
305         //TODO needs updating per sniro changes
306         public void validateCallbackResponse(DelegateExecution execution, String response){
307                 try{
308                         String placements = ""
309                         String licenses = ""
310                         if(isBlank(response)){
311                                 exceptionUtil.buildAndThrowWorkflowException(execution, 5000, "Sniro Async Callback Response is Empty")
312                         }else{
313                                 if(JsonUtils.jsonElementExist(response, "solutionInfo")){
314                                         if(JsonUtils.jsonElementExist(response, "solutionInfo.placementInfo")){
315                                                 placements = jsonUtil.getJsonValue(response, "solutionInfo.placementInfo")
316                                         }
317                                         if(JsonUtils.jsonElementExist(response, "solutionInfo.licenseInfo")){
318                                                 licenses = jsonUtil.getJsonValue(response, "solutionInfo.licenseInfo")
319                                         }
320                                         if((isBlank(placements) || placements.equalsIgnoreCase("[]")) && (isBlank(licenses) || licenses.equalsIgnoreCase("[]"))){
321                                                 msoLogger.debug("Sniro Async Response does not contain: licenses or placements")
322                                                 exceptionUtil.buildAndThrowWorkflowException(execution, 400, "Sniro Async Callback Response does not contain: licenses or placements")
323                                         }else{
324                                                 return
325                                         }
326                                 }else if(JsonUtils.jsonElementExist(response, "requestError") == true){
327                                         String errorMessage = ""
328                                         if(response.contains("policyException")){
329                                                 String text = jsonUtil.getJsonValue(response, "requestError.policyException.text")
330                                                 errorMessage = "Sniro Async Response contains a policy error: " + text
331                                         }else if(response.contains("serviceException")){
332                                                 String text = jsonUtil.getJsonValue(response, "requestError.serviceException.text")
333                                                 errorMessage = "Sniro Async Response contains a service error: " + text
334                                         }else{
335                                                 errorMessage = "Sniro Async Response contains an error: not provided"
336                                         }
337                                         msoLogger.debug("Sniro Async Response contains an error: " + errorMessage)
338                                         exceptionUtil.buildAndThrowWorkflowException(execution, 400, errorMessage)
339
340                                 }else{
341                                         msoLogger.debug("Sniro Async Response contains an error: not provided")
342                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Sniro Async Response contains an error: not provided")
343                                 }
344                         }
345                 }catch(BpmnError b){
346                         throw b
347                 }catch(Exception e){
348                         msoLogger.debug("Error encountered within Homing validateCallbackResponse method: " + e)
349                         exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Internal Error - Occured in Sniro Homing Validate Async Response")
350                 }
351         }
352
353 }