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