Merge "Add ability to build https endpoint to multicloud"
[so.git] / bpmn / MSOCommonBPMN / src / main / groovy / org / onap / so / bpmn / common / scripts / OofUtils.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2018 Intel Corp. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright (c) 2019 Samsung
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.so.bpmn.common.scripts
24
25 import com.fasterxml.jackson.databind.ObjectMapper
26 import org.camunda.bpm.engine.delegate.DelegateExecution
27 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
28 import org.onap.so.bpmn.common.scripts.ExceptionUtil
29 import org.onap.so.bpmn.common.util.OofInfraUtils
30 import org.onap.so.bpmn.core.UrnPropertiesReader
31 import org.onap.so.bpmn.core.domain.HomingSolution
32 import org.onap.so.bpmn.core.domain.ModelInfo
33 import org.onap.so.bpmn.core.domain.Resource
34 import org.onap.so.bpmn.core.domain.AllottedResource
35 import org.onap.so.bpmn.core.domain.ServiceDecomposition
36 import org.onap.so.bpmn.core.domain.ServiceInstance
37 import org.onap.so.bpmn.core.domain.Subscriber
38 import org.onap.so.bpmn.core.domain.VnfResource
39 import org.onap.so.bpmn.core.json.JsonUtils
40 import org.onap.so.client.HttpClient
41 import org.onap.so.client.HttpClientFactory
42 import org.onap.so.db.catalog.beans.CloudSite
43 import org.onap.so.db.catalog.beans.HomingInstance
44 import org.onap.logging.filter.base.ONAPComponents;
45 import org.springframework.http.HttpEntity
46 import org.springframework.http.HttpHeaders
47 import org.springframework.http.HttpMethod
48 import org.springframework.http.ResponseEntity
49 import org.springframework.http.client.BufferingClientHttpRequestFactory
50 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
51 import org.springframework.web.client.RestTemplate
52 import org.springframework.web.util.UriComponentsBuilder
53 import org.slf4j.Logger
54 import org.slf4j.LoggerFactory
55
56 import javax.ws.rs.core.MediaType
57 import javax.ws.rs.core.Response
58 import javax.ws.rs.core.UriBuilder
59 import javax.xml.ws.http.HTTPException
60
61 import static org.onap.so.bpmn.common.scripts.GenericUtils.*
62
63 class OofUtils {
64     private static final Logger logger = LoggerFactory.getLogger( OofUtils.class);
65
66     ExceptionUtil exceptionUtil = new ExceptionUtil()
67     JsonUtils jsonUtil = new JsonUtils()
68     OofInfraUtils oofInfraUtils = new OofInfraUtils()
69
70     private AbstractServiceTaskProcessor utils
71
72     OofUtils(AbstractServiceTaskProcessor taskProcessor) {
73         this.utils = taskProcessor
74     }
75
76     /**
77      * This method builds the service-agnostic
78      * OOF json request to get a homing solution
79      * and license solution
80      *
81      * @param execution
82      * @param requestId
83      * @param decomposition - ServiceDecomposition object
84      * @param customerLocation -
85      * @param existingCandidates -
86      * @param excludedCandidates -
87      * @param requiredCandidates -
88      *
89      * @return request - OOF v1 payload - https://wiki.onap.org/pages/viewpage.action?pageId=25435066
90      */
91     String buildRequest(DelegateExecution execution,
92                         String requestId,
93                         ServiceDecomposition decomposition,
94                         Subscriber subscriber = null,
95                         Map customerLocation,
96                         ArrayList existingCandidates = null,
97                         ArrayList excludedCandidates = null,
98                         ArrayList requiredCandidates = null) {
99         logger.debug( "Started Building OOF Request")
100         String callbackEndpoint = UrnPropertiesReader.getVariable("mso.oof.callbackEndpoint", execution)
101         logger.debug( "mso.oof.callbackEndpoint is: " + callbackEndpoint)
102         try {
103             def callbackUrl = utils.createHomingCallbackURL(callbackEndpoint, "oofResponse", requestId)
104             logger.debug( "callbackUrl is: " + callbackUrl)
105
106
107             def transactionId = requestId
108             logger.debug( "transactionId is: " + transactionId)
109             //ServiceInstance Info
110             ServiceInstance serviceInstance = decomposition.getServiceInstance()
111             def serviceInstanceId = ""
112             def serviceName = ""
113
114             serviceInstanceId = execution.getVariable("serviceInstanceId")
115             logger.debug( "serviceInstanceId is: " + serviceInstanceId)
116             serviceName = execution.getVariable("subscriptionServiceType")
117             logger.debug( "serviceName is: " + serviceName)
118
119             if (serviceInstanceId == null || serviceInstanceId == "null") {
120                 logger.debug( "Unable to obtain Service Instance Id")
121                 exceptionUtil.buildAndThrowWorkflowException(execution, 400, "Internal Error - Unable to " +
122                         "obtain Service Instance Id, execution.getVariable(\"serviceInstanceId\") is null")
123             }
124             if (serviceName == null || serviceName == "null") {
125                 logger.debug( "Unable to obtain Service Name")
126                 exceptionUtil.buildAndThrowWorkflowException(execution, 400, "Internal Error - Unable to " +
127                         "obtain Service Name, execution.getVariable(\"subscriptionServiceType\") is null")
128             }
129             //Model Info
130             ModelInfo model = decomposition.getModelInfo()
131             logger.debug( "ModelInfo: " + model.toString())
132             String modelType = model.getModelType()
133             String modelInvariantId = model.getModelInvariantUuid()
134             String modelVersionId = model.getModelUuid()
135             String modelName = model.getModelName()
136             String modelVersion = model.getModelVersion()
137             //Subscriber Info
138             String subscriberId = ""
139             String subscriberName = ""
140             String commonSiteId = ""
141             if (subscriber != null) {
142                 subscriberId = subscriber.getGlobalId()
143                 subscriberName = subscriber.getName()
144                 commonSiteId = subscriber.getCommonSiteId()
145             }
146
147             //Determine RequestType
148             //TODO Figure out better way to determine this
149             String requestType = "create"
150             List<Resource> resources = decomposition.getServiceResources()
151             for (Resource r : resources) {
152                 HomingSolution currentSolution = (HomingSolution) r.getCurrentHomingSolution()
153                 if (currentSolution != null) {
154                     requestType = "speed changed"
155                 }
156             }
157
158             //Demands
159             String placementDemands = ""
160             StringBuilder sb = new StringBuilder()
161             List<AllottedResource> allottedResourceList = decomposition.getAllottedResources()
162             List<VnfResource> vnfResourceList = decomposition.getVnfResources()
163
164             if (allottedResourceList == null || allottedResourceList.isEmpty()) {
165                 logger.debug( "Allotted Resources List is empty - will try to get service VNFs instead.")
166             } else {
167                 for (AllottedResource resource : allottedResourceList) {
168                     logger.debug( "Allotted Resource: " + resource.toString())
169                     def serviceResourceId = resource.getResourceId()
170                     def toscaNodeType = resource.getToscaNodeType()
171                     def resourceModuleName = toscaNodeType.substring(toscaNodeType.lastIndexOf(".") + 1)
172                     def resourceModelInvariantId = resource.getModelInfo().getModelInvariantUuid()
173                     def resourceModelVersionId = resource.getModelInfo().getModelUuid()
174                     def resourceModelName = resource.getModelInfo().getModelName()
175                     def resourceModelVersion = resource.getModelInfo().getModelVersion()
176                     def resourceModelType = resource.getModelInfo().getModelType()
177                     def tenantId = execution.getVariable("tenantId")
178                     def requiredCandidatesJson = ""
179
180                     requiredCandidatesJson = createCandidateJson(
181                             existingCandidates,
182                             excludedCandidates,
183                             requiredCandidates)
184
185                     String demand =
186                             "      {\n" +
187                                     "      \"resourceModuleName\": \"${resourceModuleName}\",\n" +
188                                     "      \"serviceResourceId\": \"${serviceResourceId}\",\n" +
189                                     "      \"tenantId\": \"${tenantId}\",\n" +
190                                     "      \"resourceModelInfo\": {\n" +
191                                     "        \"modelInvariantId\": \"${resourceModelInvariantId}\",\n" +
192                                     "        \"modelVersionId\": \"${resourceModelVersionId}\",\n" +
193                                     "        \"modelName\": \"${resourceModelName}\",\n" +
194                                     "        \"modelType\": \"${resourceModelType}\",\n" +
195                                     "        \"modelVersion\": \"${resourceModelVersion}\",\n" +
196                                     "        \"modelCustomizationName\": \"\"\n" +
197                                     "        }" + requiredCandidatesJson + "\n" +
198                                     "      },"
199
200                     placementDemands = sb.append(demand)
201                 }
202             }
203
204             if (vnfResourceList == null || vnfResourceList.isEmpty()) {
205                 logger.debug( "VNF Resources List is empty")
206             } else {
207
208                 for (VnfResource vnfResource : vnfResourceList) {
209                     logger.debug( "VNF Resource: " + vnfResource.toString())
210                     ModelInfo vnfResourceModelInfo = vnfResource.getModelInfo()
211                     def toscaNodeType = vnfResource.getToscaNodeType()
212                     def resourceModuleName = toscaNodeType.substring(toscaNodeType.lastIndexOf(".") + 1)
213                     def serviceResourceId = vnfResource.getResourceId()
214                     def resourceModelInvariantId = vnfResourceModelInfo.getModelInvariantUuid()
215                     def resourceModelName = vnfResourceModelInfo.getModelName()
216                     def resourceModelVersion = vnfResourceModelInfo.getModelVersion()
217                     def resourceModelVersionId = vnfResourceModelInfo.getModelUuid()
218                     def resourceModelType = vnfResourceModelInfo.getModelType()
219                     def tenantId = execution.getVariable("tenantId")
220                     def requiredCandidatesJson = ""
221
222
223                     String placementDemand =
224                             "      {\n" +
225                                     "      \"resourceModuleName\": \"${resourceModuleName}\",\n" +
226                                     "      \"serviceResourceId\": \"${serviceResourceId}\",\n" +
227                                     "      \"tenantId\": \"${tenantId}\",\n" +
228                                     "      \"resourceModelInfo\": {\n" +
229                                     "        \"modelInvariantId\": \"${resourceModelInvariantId}\",\n" +
230                                     "        \"modelVersionId\": \"${resourceModelVersionId}\",\n" +
231                                     "        \"modelName\": \"${resourceModelName}\",\n" +
232                                     "        \"modelType\": \"${resourceModelType}\",\n" +
233                                     "        \"modelVersion\": \"${resourceModelVersion}\",\n" +
234                                     "        \"modelCustomizationName\": \"\"\n" +
235                                     "        }" + requiredCandidatesJson + "\n" +
236                                     "      },"
237
238                     placementDemands = sb.append(placementDemand)
239                 }
240                 placementDemands = placementDemands.substring(0, placementDemands.length() - 1)
241             }
242
243             /* Commenting Out Licensing as OOF doesn't support for Beijing
244         String licenseDemands = ""
245         sb = new StringBuilder()
246         if (vnfResourceList.isEmpty() || vnfResourceList == null) {
247             logger.debug( "Vnf Resources List is Empty")
248         } else {
249             for (VnfResource vnfResource : vnfResourceList) {
250                 ModelInfo vnfResourceModelInfo = vnfResource.getModelInfo()
251                 def resourceInstanceType = vnfResource.getResourceType()
252                 def serviceResourceId = vnfResource.getResourceId()
253                 def resourceModuleName = vnfResource.getResourceType()
254                 def resouceModelInvariantId = vnfResourceModelInfo.getModelInvariantUuid()
255                 def resouceModelName = vnfResourceModelInfo.getModelName()
256                 def resouceModelVersion = vnfResourceModelInfo.getModelVersion()
257                 def resouceModelVersionId = vnfResourceModelInfo.getModelUuid()
258                 def resouceModelType = vnfResourceModelInfo.getModelType()
259
260                 // TODO Add Existing Licenses to demand
261                 //"existingLicenses": {
262                 //"entitlementPoolUUID": ["87257b49-9602-4ca1-9817-094e52bc873b",
263                 // "43257b49-9602-4fe5-9337-094e52bc9435"],
264                 //"licenseKeyGroupUUID": ["87257b49-9602-4ca1-9817-094e52bc873b",
265                 // "43257b49-9602-4fe5-9337-094e52bc9435"]
266                 //}
267
268                     String licenseDemand =
269                         "{\n" +
270                         "\"resourceModuleName\": \"${resourceModuleName}\",\n" +
271                         "\"serviceResourceId\": \"${serviceResourceId}\",\n" +
272                         "\"resourceInstanceType\": \"${resourceInstanceType}\",\n" +
273                         "\"resourceModelInfo\": {\n" +
274                         "  \"modelInvariantId\": \"${resouceModelInvariantId}\",\n" +
275                         "  \"modelVersionId\": \"${resouceModelVersionId}\",\n" +
276                         "  \"modelName\": \"${resouceModelName}\",\n" +
277                         "  \"modelType\": \"${resouceModelType}\",\n" +
278                         "  \"modelVersion\": \"${resouceModelVersion}\",\n" +
279                         "  \"modelCustomizationName\": \"\"\n" +
280                         "  }\n"
281                         "},"
282
283                 licenseDemands = sb.append(licenseDemand)
284             }
285             licenseDemands = licenseDemands.substring(0, licenseDemands.length() - 1)
286         }*/
287
288             String request =
289                     "{\n" +
290                             "  \"requestInfo\": {\n" +
291                             "    \"transactionId\": \"${transactionId}\",\n" +
292                             "    \"requestId\": \"${requestId}\",\n" +
293                             "    \"callbackUrl\": \"${callbackUrl}\",\n" +
294                             "    \"sourceId\": \"so\",\n" +
295                             "    \"requestType\": \"${requestType}\"," +
296                             "    \"numSolutions\": 1,\n" +
297                             "    \"optimizers\": [\"placement\"],\n" +
298                             "    \"timeout\": 600\n" +
299                             "    },\n" +
300                             "  \"placementInfo\": {\n" +
301                             "    \"requestParameters\": {\n" +
302                             "      \"customerLatitude\": \"${customerLocation.customerLatitude}\",\n" +
303                             "      \"customerLongitude\": \"${customerLocation.customerLongitude}\",\n" +
304                             "      \"customerName\": \"${customerLocation.customerName}\"\n" +
305                             "    }," +
306                             "    \"subscriberInfo\": { \n" +
307                             "      \"globalSubscriberId\": \"${subscriberId}\",\n" +
308                             "      \"subscriberName\": \"${subscriberName}\",\n" +
309                             "      \"subscriberCommonSiteId\": \"${commonSiteId}\"\n" +
310                             "    },\n" +
311                             "    \"placementDemands\": [\n" +
312                             "      ${placementDemands}\n" +
313                             "      ]\n" +
314                             "    },\n" +
315                             "  \"serviceInfo\": {\n" +
316                             "    \"serviceInstanceId\": \"${serviceInstanceId}\",\n" +
317                             "    \"serviceName\": \"${serviceName}\",\n" +
318                             "    \"modelInfo\": {\n" +
319                             "      \"modelType\": \"${modelType}\",\n" +
320                             "      \"modelInvariantId\": \"${modelInvariantId}\",\n" +
321                             "      \"modelVersionId\": \"${modelVersionId}\",\n" +
322                             "      \"modelName\": \"${modelName}\",\n" +
323                             "      \"modelVersion\": \"${modelVersion}\",\n" +
324                             "      \"modelCustomizationName\": \"\"\n" +
325                             "    }\n" +
326                             "  }\n" +
327                             "}"
328
329
330             logger.debug( "Completed Building OOF Request")
331             return request
332         } catch (Exception ex) {
333              logger.debug( "buildRequest Exception: " + ex)
334         }
335     }
336
337     /**
338      * This method validates the callback response
339      * from OOF. If the response contains an
340      * exception the method will build and throw
341      * a workflow exception.
342      *
343      * @param execution
344      * @param response - the async callback response from oof
345      */
346     Void validateCallbackResponse(DelegateExecution execution, String response) {
347         String placements = ""
348         if (isBlank(response)) {
349             exceptionUtil.buildAndThrowWorkflowException(execution, 5000, "OOF Async Callback Response is Empty")
350         } else {
351             if (JsonUtils.jsonElementExist(response, "solutions.placementSolutions")) {
352                 placements = jsonUtil.getJsonValue(response, "solutions.placementSolutions")
353                 if (isBlank(placements) || placements.equalsIgnoreCase("[]")) {
354                     String statusMessage = jsonUtil.getJsonValue(response, "statusMessage")
355                     if (isBlank(statusMessage)) {
356                         logger.debug( "Error Occurred in Homing: OOF Async Callback Response does " +
357                                 "not contain placement solution.")
358                         exceptionUtil.buildAndThrowWorkflowException(execution, 400,
359                                 "OOF Async Callback Response does not contain placement solution.")
360                     } else {
361                         logger.debug( "Error Occurred in Homing: " + statusMessage)
362                         exceptionUtil.buildAndThrowWorkflowException(execution, 400, statusMessage)
363                     }
364                 } else {
365                     return
366                 }
367             } else if (response.contains("error") || response.contains("Error") ) {
368                 String errorMessage = ""
369                 if (response.contains("policyException")) {
370                     String text = jsonUtil.getJsonValue(response, "requestError.policyException.text")
371                     errorMessage = "OOF Async Callback Response contains a Request Error Policy Exception: " + text
372                 } else if (response.contains("Unable to find any candidate for demand")) {
373                     errorMessage = "OOF Async Callback Response contains error: Unable to find any candidate for " +
374                             "demand *** Response: " + response.toString()
375                 } else if (response.contains("serviceException")) {
376                     String text = jsonUtil.getJsonValue(response, "requestError.serviceException.text")
377                     errorMessage = "OOF Async Callback Response contains a Request Error Service Exception: " + text
378                 } else {
379                     errorMessage = "OOF Async Callback Response contains a Request Error. Unable to determine the Request Error Exception."
380                 }
381                 logger.debug( "Error Occurred in Homing: " + errorMessage)
382                 exceptionUtil.buildAndThrowWorkflowException(execution, 400, errorMessage)
383
384             } else {
385                 logger.debug( "Error Occurred in Homing: Received an Unknown Async Callback Response from OOF.")
386                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Received an Unknown Async Callback Response from OOF.")
387             }
388         }
389
390     }
391
392     /**
393      * This method creates candidates json for placement Demands.
394      *
395      * @param execution
396      * @param existingCandidates -
397      * @param excludedCandidates -
398      * @param requiredCandidates -
399      *
400      * @return candidatesJson - a JSON string with candidates
401      */
402     String createCandidateJson(ArrayList existingCandidates = null,
403                                ArrayList excludedCandidates = null,
404                                ArrayList requiredCandidates = null) {
405         def candidatesJson = ""
406         def type = ""
407         if (existingCandidates != null && existingCandidates != {}) {
408             sb = new StringBuilder()
409             sb.append(",\n" +
410                     "  \"existingCandidates\": [\n")
411             def existingCandidateJson = ""
412             existingCandidates.each { existingCandidate ->
413                 type = existingCandidate.get('identifierType')
414                 if (type == 'vimId') {
415                     def cloudOwner = existingCandidate.get('cloudOwner')
416                     def cloudRegionId = existingCandidate.get('identifiers')
417                     existingCandidateJson = "{\n" +
418                             "    \"identifierType\": \"vimId\",\n" +
419                             "    \"cloudOwner\": \"${cloudOwner}\",\n" +
420                             "    \"identifiers\": [\"${cloudRegionId}\"]\n" +
421                             "    },"
422                     sb.append(existingCandidateJson)
423                 }
424                 if (type == 'serviceInstanceId') {
425                     def serviceInstanceId = existingCandidate.get('identifiers')
426                     existingCandidateJson += "{\n" +
427                             "    \"identifierType\": \"serviceInstanceId\",\n" +
428                             "    \"identifiers\": [\"${serviceInstanceId}\"]\n" +
429                             "    },"
430                     sb.append(existingCandidateJson)
431                 }
432             }
433             if (existingCandidateJson != "") {
434                 sb.setLength(sb.length() - 1)
435                 candidatesJson = sb.append(",\n],")
436             }
437         }
438         if (excludedCandidates != null && excludedCandidates != {}) {
439             sb = new StringBuilder()
440             sb.append(",\n" +
441                     "  \"excludedCandidates\": [\n")
442             def excludedCandidateJson = ""
443             excludedCandidates.each { excludedCandidate ->
444                 type = excludedCandidate.get('identifierType')
445                 if (type == 'vimId') {
446                     def cloudOwner = excludedCandidate.get('cloudOwner')
447                     def cloudRegionId = excludedCandidate.get('identifiers')
448                     excludedCandidateJson = "{\n" +
449                             "    \"identifierType\": \"vimId\",\n" +
450                             "    \"cloudOwner\": \"${cloudOwner}\",\n" +
451                             "    \"identifiers\": [\"${cloudRegionId}\"]\n" +
452                             "    },"
453                     sb.append(excludedCandidateJson)
454                 }
455                 if (type == 'serviceInstanceId') {
456                     def serviceInstanceId = excludedCandidate.get('identifiers')
457                     excludedCandidateJson += "{\n" +
458                             "    \"identifierType\": \"serviceInstanceId\",\n" +
459                             "    \"identifiers\": [\"${serviceInstanceId}\"]\n" +
460                             "    },"
461                     sb.append(excludedCandidateJson)
462                 }
463             }
464             if (excludedCandidateJson != "") {
465                 sb.setLength(sb.length() - 1)
466                 candidatesJson = sb.append(",\n],")
467             }
468         }
469         if (requiredCandidates != null && requiredCandidates != {}) {
470             sb = new StringBuilder()
471             sb.append(",\n" +
472                     "  \"requiredCandidates\": [\n")
473             def requiredCandidatesJson = ""
474             requiredCandidates.each { requiredCandidate ->
475                 type = requiredCandidate.get('identifierType')
476                 if (type == 'vimId') {
477                     def cloudOwner = requiredCandidate.get('cloudOwner')
478                     def cloudRegionId = requiredCandidate.get('identifiers')
479                     requiredCandidatesJson = "{\n" +
480                             "    \"identifierType\": \"vimId\",\n" +
481                             "    \"cloudOwner\": \"${cloudOwner}\",\n" +
482                             "    \"identifiers\": [\"${cloudRegionId}\"]\n" +
483                             "    },"
484                     sb.append(requiredCandidatesJson)
485                 }
486                 if (type == 'serviceInstanceId') {
487                     def serviceInstanceId = requiredCandidate.get('identifiers')
488                     requiredCandidatesJson += "{\n" +
489                             "    \"identifierType\": \"serviceInstanceId\",\n" +
490                             "    \"identifiers\": [\"${serviceInstanceId}\"]\n" +
491                             "    },"
492                     sb.append(requiredCandidatesJson)
493                 }
494             }
495             if (requiredCandidatesJson != "") {
496                 sb.setLength(sb.length() - 1)
497                 candidatesJson = sb.append(",\n],")
498             }
499         }
500         if (candidatesJson != "") {candidatesJson = candidatesJson.substring(0, candidatesJson.length() - 1)}
501         return candidatesJson
502     }
503
504     /**
505      * This method creates a cloudsite in catalog database.
506      *
507      * @param CloudSite cloudSite
508      *
509      * @return void
510      */
511     Void createCloudSite(CloudSite cloudSite, DelegateExecution execution) {
512         oofInfraUtils.createCloudSite(cloudSite, execution)
513     }
514
515     /**
516      * This method creates a HomingInstance in catalog database.
517      *
518      * @param HomingInstance homingInstance
519      *
520      * @return void
521      */
522     Void createHomingInstance(HomingInstance homingInstance, DelegateExecution execution) {
523         oofInfraUtils.createHomingInstance(homingInstance, execution)
524     }
525
526     String getMsbHost(DelegateExecution execution) {
527         String msbHost = UrnPropertiesReader.getVariable("mso.msb.host", execution, "msb-iag.onap")
528
529         Integer msbPort = UrnPropertiesReader.getVariable("mso.msb.port", execution, "80").toInteger()
530
531         return UriBuilder.fromPath("").host(msbHost).port(msbPort).scheme("http").build().toString()
532     }
533
534     public String buildSelectNSTRequest(String requestId, Map<String, Object> profileInfo) {
535         def transactionId = requestId
536         logger.debug( "transactionId is: " + transactionId)
537         ObjectMapper objectMapper = new ObjectMapper()
538         String json = objectMapper.writeValueAsString(profileInfo)
539         StringBuilder response = new StringBuilder()
540         response.append(
541                 "{\n" +
542                         "  \"requestInfo\": {\n" +
543                         "    \"transactionId\": \"${transactionId}\",\n" +
544                         "    \"requestId\": \"${requestId}\",\n" +
545                         "    \"sourceId\": \"so\",\n" +
546                         "    \"timeout\": 600\n" +
547                         "    },\n")
548         response.append(",\n \"serviceInfo\": \n")
549         response.append(json);
550         response.append("\n  }\n")
551         return response.toString()
552     }
553 }