2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. 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
13 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
23 package org.onap.so.bpmn.common.scripts
25 import org.onap.so.logger.LoggingAnchor
26 import org.onap.so.client.HttpClientFactory
27 import org.onap.so.logger.ErrorCode
29 import javax.ws.rs.core.Response
30 import org.apache.commons.lang3.*
31 import org.camunda.bpm.engine.delegate.BpmnError
32 import org.camunda.bpm.engine.delegate.DelegateExecution
33 import org.onap.so.bpmn.core.UrnPropertiesReader
34 import org.onap.so.client.HttpClient
35 import org.onap.so.logger.MessageEnum
36 import org.slf4j.Logger
37 import org.slf4j.LoggerFactory
38 import org.onap.so.utils.TargetEntity
44 class VnfAdapterRestV1 extends AbstractServiceTaskProcessor {
45 private static final Logger logger = LoggerFactory.getLogger( VnfAdapterRestV1.class);
48 ExceptionUtil exceptionUtil = new ExceptionUtil()
50 // VNF Response Processing
51 public void preProcessRequest (DelegateExecution execution) {
52 def method = getClass().getSimpleName() + '.preProcessRequest(' +
53 'execution=' + execution.getId() +
55 logger.trace('Entered ' + method)
58 execution.setVariable("prefix", prefix)
59 setSuccessIndicator(execution, false)
62 String request = validateRequest(execution, "mso-request-id")
64 // Get the request type (the name of the root element) from the request
66 Node root = new XmlParser().parseText(request)
67 String requestType = root.name()
68 execution.setVariable(prefix + 'requestType', requestType)
69 logger.debug(getProcessKey(execution) + ': ' + prefix + 'requestType = ' + requestType)
71 logger.debug('VnfAdapterRestV1, request: ' + request)
72 // Get the messageId from the request
74 String messageId = getChildText(root, 'messageId')
76 if ('rollbackVolumeGroupRequest'.equals(requestType)) {
77 messageId = getMessageIdForVolumeGroupRollback(root)
80 if (messageId == null || messageId.isEmpty()) {
81 String msg = getProcessKey(execution) + ': no messageId in ' + requestType
82 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
83 ErrorCode.UnknownError.getValue());
84 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
87 execution.setVariable('VNFAResponse_CORRELATOR', messageId)
88 logger.debug(getProcessKey(execution) + ': VNFAResponse_CORRELATOR = ' + messageId)
90 // Get the notificationUrl from the request
92 String notificationUrl = getChildText(root, 'notificationUrl')
94 if (notificationUrl == null || notificationUrl.isEmpty()) {
95 String msg = getProcessKey(execution) + ': no notificationUrl in ' + requestType
96 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
97 ErrorCode.UnknownError.getValue());
98 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
101 execution.setVariable(prefix + 'notificationUrl', notificationUrl)
102 logger.debug(getProcessKey(execution) + ': ' + prefix + 'notificationUrl = ' + notificationUrl)
104 // Determine the VnfAdapter endpoint
106 String vnfAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.vnf.rest.endpoint", execution)
108 if (vnfAdapterEndpoint == null || vnfAdapterEndpoint.isEmpty()) {
109 String msg = getProcessKey(execution) + ': mso:adapters:vnf:rest:endpoint URN mapping is not defined'
110 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
111 ErrorCode.UnknownError.getValue());
112 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
115 while (vnfAdapterEndpoint.endsWith('/')) {
116 vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, vnfAdapterEndpoint.length()-1)
119 String vnfAdapterMethod = null
120 String vnfAdapterUrl = null
121 String vnfAdapterRequest = request
123 if ('createVfModuleRequest'.equals(requestType)) {
124 String vnfId = getChildText(root, 'vnfId')
126 if (vnfId == null || vnfId.isEmpty()) {
127 String msg = getProcessKey(execution) + ': no vnfId in ' + requestType
128 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
129 ErrorCode.UnknownError.getValue());
130 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
133 vnfAdapterMethod = 'POST'
134 vnfAdapterUrl = vnfAdapterEndpoint + '/' + URLEncoder.encode(vnfId, 'UTF-8') + '/vf-modules'
136 } else if ('updateVfModuleRequest'.equals(requestType)) {
137 String vnfId = getChildText(root, 'vnfId')
139 if (vnfId == null || vnfId.isEmpty()) {
140 String msg = getProcessKey(execution) + ': no vnfId in ' + requestType
141 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
142 ErrorCode.UnknownError.getValue());
143 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
146 String vfModuleId = getChildText(root, 'vfModuleId')
148 if (vfModuleId == null || vfModuleId.isEmpty()) {
149 String msg = getProcessKey(execution) + ': no vfModuleId in ' + requestType
150 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
151 ErrorCode.UnknownError.getValue());
152 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
155 vnfAdapterMethod = 'PUT'
156 vnfAdapterUrl = vnfAdapterEndpoint + '/' + URLEncoder.encode(vnfId, 'UTF-8') +
157 '/vf-modules/' + URLEncoder.encode(vfModuleId, 'UTF-8')
159 } else if ('deleteVfModuleRequest'.equals(requestType)) {
160 String vnfId = getChildText(root, 'vnfId')
162 if (vnfId == null || vnfId.isEmpty()) {
163 String msg = getProcessKey(execution) + ': no vnfId in ' + requestType
164 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
165 ErrorCode.UnknownError.getValue());
166 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
169 String vfModuleId = getChildText(root, 'vfModuleId')
171 if (vfModuleId == null || vfModuleId.isEmpty()) {
172 String msg = getProcessKey(execution) + ': no vfModuleId in ' + requestType
173 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
174 ErrorCode.UnknownError.getValue());
175 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
178 vnfAdapterMethod = 'DELETE'
179 vnfAdapterUrl = vnfAdapterEndpoint + '/' + URLEncoder.encode(vnfId, 'UTF-8') +
180 '/vf-modules/' + URLEncoder.encode(vfModuleId, 'UTF-8')
182 } else if ('rollbackVfModuleRequest'.equals(requestType)) {
183 Node vfModuleRollbackNode = getChild(root, 'vfModuleRollback')
185 if (vfModuleRollbackNode == null) {
186 String msg = getProcessKey(execution) + ': no vfModuleRollback in ' + requestType
187 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
188 ErrorCode.UnknownError.getValue());
189 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
192 String vnfId = getChildText(vfModuleRollbackNode, 'vnfId')
194 if (vnfId == null || vnfId.isEmpty()) {
195 String msg = getProcessKey(execution) + ': no vnfId in ' + requestType
196 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
197 ErrorCode.UnknownError.getValue());
198 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
201 String vfModuleId = getChildText(vfModuleRollbackNode, 'vfModuleId')
203 if (vfModuleId == null || vfModuleId.isEmpty()) {
204 String msg = getProcessKey(execution) + ': no vfModuleId in ' + requestType
205 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
206 ErrorCode.UnknownError.getValue());
207 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
210 vnfAdapterMethod = 'DELETE'
211 vnfAdapterUrl = vnfAdapterEndpoint + '/' + URLEncoder.encode(vnfId, 'UTF-8') +
212 '/vf-modules/' + URLEncoder.encode(vfModuleId, 'UTF-8') + '/rollback'
214 } else if ('createVolumeGroupRequest'.equals(requestType)) {
215 vnfAdapterMethod = 'POST'
216 if (vnfAdapterEndpoint.endsWith('v1/vnfs')) {
217 vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, (vnfAdapterEndpoint.length()-'/vnfs'.length()))
219 vnfAdapterUrl = vnfAdapterEndpoint + '/volume-groups'
221 } else if ('updateVolumeGroupRequest'.equals(requestType)) {
222 String volumeGroupId = getChildText(root, 'volumeGroupId')
224 if (volumeGroupId == null || volumeGroupId.isEmpty()) {
225 String msg = getProcessKey(execution) + ': no volumeGroupId in ' + requestType
226 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
227 ErrorCode.UnknownError.getValue());
228 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
231 vnfAdapterMethod = 'PUT'
232 if (vnfAdapterEndpoint.endsWith('v1/vnfs')) {
233 vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, (vnfAdapterEndpoint.length()-'/vnfs'.length()))
235 vnfAdapterUrl = vnfAdapterEndpoint + '/volume-groups/' + URLEncoder.encode(volumeGroupId, 'UTF-8')
237 } else if ('deleteVolumeGroupRequest'.equals(requestType)) {
238 String volumeGroupId = getChildText(root, 'volumeGroupId')
240 if (volumeGroupId == null || volumeGroupId.isEmpty()) {
241 String msg = getProcessKey(execution) + ': no volumeGroupId in ' + requestType
242 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
243 ErrorCode.UnknownError.getValue());
244 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
247 vnfAdapterMethod = 'DELETE'
248 if (vnfAdapterEndpoint.endsWith('v1/vnfs')) {
249 vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, (vnfAdapterEndpoint.length()-'/vnfs'.length()))
251 vnfAdapterUrl = vnfAdapterEndpoint + '/volume-groups/' + URLEncoder.encode(volumeGroupId, 'UTF-8')
253 } else if ('rollbackVolumeGroupRequest'.equals(requestType)) {
254 String volumeGroupId = getVolumeGroupIdFromRollbackRequest(root)
256 if (volumeGroupId == null || volumeGroupId.isEmpty()) {
257 String msg = getProcessKey(execution) + ': no volumeGroupId in ' + requestType
258 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
259 ErrorCode.UnknownError.getValue());
260 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
263 vnfAdapterMethod = 'DELETE'
264 if (vnfAdapterEndpoint.endsWith('v1/vnfs')) {
265 vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, (vnfAdapterEndpoint.length()-'/vnfs'.length()))
267 vnfAdapterUrl = vnfAdapterEndpoint + '/volume-groups/' + URLEncoder.encode(volumeGroupId, 'UTF-8') + '/rollback'
270 String msg = getProcessKey(execution) + ': Unsupported request type: ' + requestType
271 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
272 ErrorCode.UnknownError.getValue());
273 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
276 execution.setVariable(prefix + 'vnfAdapterMethod', vnfAdapterMethod)
277 logger.debug(getProcessKey(execution) + ': ' + prefix + 'vnfAdapterMethod = ' + vnfAdapterMethod)
278 execution.setVariable(prefix + 'vnfAdapterUrl', vnfAdapterUrl)
279 logger.debug(getProcessKey(execution) + ': ' + prefix + 'vnfAdapterUrl = ' + vnfAdapterUrl)
280 execution.setVariable(prefix + 'vnfAdapterRequest', vnfAdapterRequest)
281 logger.debug(getProcessKey(execution) + ': ' + prefix + 'vnfAdapterRequest = \n' + vnfAdapterRequest)
283 // Get the Basic Auth credentials for the VnfAdapter
285 String basicAuthValue = UrnPropertiesReader.getVariable("mso.adapters.po.auth", execution)
287 if (basicAuthValue == null || basicAuthValue.isEmpty()) {
288 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
289 getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined", "BPMN",
290 ErrorCode.UnknownError.getValue());
293 def encodedString = utils.getBasicAuth(basicAuthValue, UrnPropertiesReader.getVariable("mso.msoKey", execution))
294 execution.setVariable(prefix + 'basicAuthHeaderValue', encodedString)
295 } catch (IOException ex) {
296 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
297 getProcessKey(execution) + ": Unable to encode BasicAuth credentials for VnfAdapter",
298 "BPMN", ErrorCode.UnknownError.getValue(), ex);
302 } catch (BpmnError e) {
303 logger.debug(" Rethrowing MSOWorkflowException")
305 } catch (Exception e) {
306 String msg = 'Caught exception in ' + method + ": " + e
307 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
308 ErrorCode.UnknownError.getValue());
310 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
314 public String getVolumeGroupIdFromRollbackRequest(Node root) {
315 return root.'volumeGroupRollback'.'volumeGroupId'.text()
318 public String getMessageIdForVolumeGroupRollback(Node root) {
319 return root.'volumeGroupRollback'.'messageId'.text()
323 * This method is used instead of an HTTP Connector task because the
324 * connector does not allow DELETE with a body.
326 public void sendRequestToVnfAdapter(DelegateExecution execution) {
327 def method = getClass().getSimpleName() + '.sendRequestToVnfAdapter(' +
328 'execution=' + execution.getId() +
330 logger.trace('Entered ' + method)
332 String prefix = execution.getVariable('prefix')
335 String vnfAdapterMethod = execution.getVariable(prefix + 'vnfAdapterMethod')
336 String vnfAdapterUrl = execution.getVariable(prefix + 'vnfAdapterUrl')
337 String vnfAdapterRequest = execution.getVariable(prefix + 'vnfAdapterRequest')
339 URL url = new URL(vnfAdapterUrl);
341 HttpClient httpClient = new HttpClientFactory().newXmlClient(url, TargetEntity.VNF_ADAPTER)
342 httpClient.addAdditionalHeader("Authorization", execution.getVariable(prefix + "basicAuthHeaderValue"))
344 httpClient.addAdditionalHeader("X-ONAP-RequestID", execution.getVariable("mso-request-id"))
345 httpClient.addAdditionalHeader("X-ONAP-InvocationID", UUID.randomUUID().toString())
346 httpClient.addAdditionalHeader("X-ONAP-PartnerName", "SO-VNFAdapter")
349 if ("GET".equals(vnfAdapterMethod)) {
350 response = httpClient.get()
351 } else if ("PUT".equals(vnfAdapterMethod)) {
352 response = httpClient.put(vnfAdapterRequest)
353 } else if ("POST".equals(vnfAdapterMethod)) {
354 response = httpClient.post(vnfAdapterRequest)
355 } else if ("DELETE".equals(vnfAdapterMethod)) {
356 response = httpClient.delete(vnfAdapterRequest)
358 String msg = 'Unsupported HTTP method "' + vnfAdapterMethod + '" in ' + method + ": " + e
359 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
360 ErrorCode.UnknownError.getValue());
361 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
364 execution.setVariable(prefix + "vnfAdapterStatusCode", response.getStatus())
365 if(response.hasEntity()){
366 execution.setVariable(prefix + "vnfAdapterResponse", response.readEntity(String.class))
368 } catch (BpmnError e) {
370 } catch (Exception e) {
371 String msg = 'Caught exception in ' + method + ": " + e
372 logger.error(LoggingAnchor.FOUR, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
373 ErrorCode.UnknownError.getValue());
374 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
378 public void processCallback(DelegateExecution execution){
379 def method = getClass().getSimpleName() + '.processCallback(' +
380 'execution=' + execution.getId() +
382 logger.trace('Entered ' + method)
384 String callback = execution.getVariable('VNFAResponse_MESSAGE')
387 logger.debug(getProcessKey(execution) + ": received callback:\n" + callback)
389 // The XML callback is available to the calling flow in any case,
390 // even if a WorkflowException is generated.
391 execution.setVariable(getProcessKey(execution) + 'Response', callback)
392 // TODO: Should deprecate use of processKey+Response variable for the response. Will use "WorkflowResponse" instead.
393 execution.setVariable("WorkflowResponse", callback)
395 callback = utils.removeXmlPreamble(callback)
397 Node root = new XmlParser().parseText(callback)
398 if (root.name().endsWith('Exception')) {
399 vnfAdapterWorkflowException(execution, callback)
401 } catch (Exception e) {
402 logger.debug("Error encountered within VnfAdapterRest ProcessCallback method: {}", e.getMessage(), e)
403 exceptionUtil.buildAndThrowWorkflowException(execution, 7020, "Error encountered within VnfAdapterRest ProcessCallback method")
408 * Tries to parse the response as XML to extract the information to create
409 * a WorkflowException. If the response cannot be parsed, a more generic
410 * WorkflowException is created.
412 public void vnfAdapterWorkflowException(DelegateExecution execution, Object response) {
414 Node root = new XmlParser().parseText(response)
415 String category = getChildText(root, "category")
416 category = category == null || category.isEmpty() ? "" : " category='" + category + "'"
417 String message = getChildText(root, "message")
418 message = message == null || message.isEmpty() ? "" : " message='" + message + "'"
419 String rolledBack = getChildText(root, "rolledBack")
420 rolledBack = rolledBack == null || rolledBack.isEmpty() ? "" : " rolledBack='" + rolledBack + "'"
421 exceptionUtil.buildWorkflowException(execution, 7020, "Received " + root.name() +
422 " from VnfAdapter:" + category + message + rolledBack);
423 } catch (Exception e) {
424 response = response == null || String.valueOf(response).isEmpty() ? "NONE" : response
425 exceptionUtil.buildWorkflowException(execution, 7020, "Received error from VnfAdapter: " + response)
430 * Gets the named child of the specified node.
431 * @param node the node
432 * @param name the child name
433 * @return the child node, or null if no such child exists
435 private Node getChild(Node node, String name) {
436 for (Node child : node.children()) {
437 if (child.name() == name) {
445 * Gets the text of the named child of the specified node.
446 * @param node the node
447 * @param name the child name
448 * @return the child node text, or null if no such child exists
450 private String getChildText(Node node, String name) {
451 Node child = getChild(node, name)
452 return child == null ? null : child.text()
455 public Logger getLogger() {