[MSO-8] Update the maven dependency
[so.git] / bpmn / MSOCommonBPMN / src / main / groovy / org / openecomp / mso / bpmn / common / scripts / VnfAdapterRestV1.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * OPENECOMP - MSO
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.openecomp.mso.bpmn.common.scripts
22
23 import org.apache.commons.lang3.*
24 import org.camunda.bpm.engine.delegate.BpmnError
25 import org.camunda.bpm.engine.runtime.Execution
26 import org.openecomp.mso.rest.APIResponse
27 import org.openecomp.mso.rest.RESTClient
28 import org.openecomp.mso.rest.RESTConfig
29
30 class VnfAdapterRestV1 extends AbstractServiceTaskProcessor {
31
32         ExceptionUtil exceptionUtil = new ExceptionUtil()
33
34         // VNF Response Processing
35         public void preProcessRequest (Execution execution) {
36                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
37                         'execution=' + execution.getId() +
38                         ')'
39                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
40                 logDebug('Entered ' + method, isDebugLogEnabled)
41
42                 def prefix="VNFREST_"
43                 execution.setVariable("prefix", prefix)
44                 setSuccessIndicator(execution, false)
45
46                 try {
47                         String request = validateRequest(execution, "mso-request-id")
48
49                         // Get the request type (the name of the root element) from the request
50
51                         Node root = new XmlParser().parseText(request)
52                         String requestType = root.name()
53                         execution.setVariable(prefix + 'requestType', requestType)
54                         logDebug(getProcessKey(execution) + ': ' + prefix + 'requestType = ' + requestType, isDebugLogEnabled)
55
56                         utils.logAudit('VnfAdapterRestV1, request: ' + request)
57                         // Get the messageId from the request
58
59                         String messageId = getChildText(root, 'messageId')
60
61                         if (messageId == null || messageId.isEmpty()) {
62                                 String msg = getProcessKey(execution) + ': no messageId in ' + requestType
63                                 logError(msg)
64                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
65                         }
66
67                         execution.setVariable('VNFAResponse_CORRELATOR', messageId)
68                         logDebug(getProcessKey(execution) + ': VNFAResponse_CORRELATOR = ' + messageId, isDebugLogEnabled)
69
70                         // Get the notificationUrl from the request
71
72                         String notificationUrl = getChildText(root, 'notificationUrl')
73
74                         if (notificationUrl == null || notificationUrl.isEmpty()) {
75                                 String msg = getProcessKey(execution) + ': no notificationUrl in ' + requestType
76                                 logError(msg)
77                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
78                         }
79
80                         execution.setVariable(prefix + 'notificationUrl', notificationUrl)
81                         logDebug(getProcessKey(execution) + ': ' + prefix + 'notificationUrl = ' + notificationUrl, isDebugLogEnabled)
82
83                         // Determine the VnfAdapter endpoint
84
85                         String vnfAdapterEndpoint = execution.getVariable("URN_mso_adapters_vnf_rest_endpoint")
86
87                         if (vnfAdapterEndpoint == null || vnfAdapterEndpoint.isEmpty()) {
88                                 String msg = getProcessKey(execution) + ': mso:adapters:vnf:rest:endpoint URN mapping is not defined'
89                                 logError(msg)
90                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
91                         }
92
93                         while (vnfAdapterEndpoint.endsWith('/')) {
94                                 vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, vnfAdapterEndpoint.length()-1)
95                         }
96
97                         String vnfAdapterMethod = null
98                         String vnfAdapterUrl = null
99                         String vnfAdapterRequest = request
100
101                         if ('createVfModuleRequest'.equals(requestType)) {
102                                 String vnfId = getChildText(root, 'vnfId')
103
104                                 if (vnfId == null || vnfId.isEmpty()) {
105                                         String msg = getProcessKey(execution) + ': no vnfId in ' + requestType
106                                         logError(msg)
107                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
108                                 }
109
110                                 vnfAdapterMethod = 'POST'
111                                 vnfAdapterUrl = vnfAdapterEndpoint + '/' + URLEncoder.encode(vnfId, 'UTF-8') + '/vf-modules'
112
113                         } else if ('updateVfModuleRequest'.equals(requestType)) {
114                                 String vnfId = getChildText(root, 'vnfId')
115
116                                 if (vnfId == null || vnfId.isEmpty()) {
117                                         String msg = getProcessKey(execution) + ': no vnfId in ' + requestType
118                                         logError(msg)
119                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
120                                 }
121
122                                 String vfModuleId = getChildText(root, 'vfModuleId')
123
124                                 if (vfModuleId == null || vfModuleId.isEmpty()) {
125                                         String msg = getProcessKey(execution) + ': no vfModuleId in ' + requestType
126                                         logError(msg)
127                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
128                                 }
129
130                                 vnfAdapterMethod = 'PUT'
131                                 vnfAdapterUrl = vnfAdapterEndpoint + '/' + URLEncoder.encode(vnfId, 'UTF-8') +
132                                         '/vf-modules/' + URLEncoder.encode(vfModuleId, 'UTF-8')
133
134                         } else if ('deleteVfModuleRequest'.equals(requestType)) {
135                                 String vnfId = getChildText(root, 'vnfId')
136
137                                 if (vnfId == null || vnfId.isEmpty()) {
138                                         String msg = getProcessKey(execution) + ': no vnfId in ' + requestType
139                                         logError(msg)
140                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
141                                 }
142
143                                 String vfModuleId = getChildText(root, 'vfModuleId')
144
145                                 if (vfModuleId == null || vfModuleId.isEmpty()) {
146                                         String msg = getProcessKey(execution) + ': no vfModuleId in ' + requestType
147                                         logError(msg)
148                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
149                                 }
150
151                                 vnfAdapterMethod = 'DELETE'
152                                 vnfAdapterUrl = vnfAdapterEndpoint + '/' + URLEncoder.encode(vnfId, 'UTF-8') +
153                                         '/vf-modules/' + URLEncoder.encode(vfModuleId, 'UTF-8')
154
155                         } else if ('rollbackVfModuleRequest'.equals(requestType)) {
156                                 Node vfModuleRollbackNode = getChild(root, 'vfModuleRollback')
157
158                                 if (vfModuleRollbackNode == null) {
159                                         String msg = getProcessKey(execution) + ': no vfModuleRollback in ' + requestType
160                                         logError(msg)
161                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
162                                 }
163
164                                 String vnfId = getChildText(vfModuleRollbackNode, 'vnfId')
165
166                                 if (vnfId == null || vnfId.isEmpty()) {
167                                         String msg = getProcessKey(execution) + ': no vnfId in ' + requestType
168                                         logError(msg)
169                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
170                                 }
171
172                                 String vfModuleId = getChildText(vfModuleRollbackNode, 'vfModuleId')
173
174                                 if (vfModuleId == null || vfModuleId.isEmpty()) {
175                                         String msg = getProcessKey(execution) + ': no vfModuleId in ' + requestType
176                                         logError(msg)
177                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
178                                 }
179
180                                 vnfAdapterMethod = 'DELETE'
181                                 vnfAdapterUrl = vnfAdapterEndpoint + '/' + URLEncoder.encode(vnfId, 'UTF-8') +
182                                         '/vf-modules/' + URLEncoder.encode(vfModuleId, 'UTF-8') + '/rollback'
183
184                         } else if ('createVolumeGroupRequest'.equals(requestType)) {
185                                 vnfAdapterMethod = 'POST'
186                                 if (vnfAdapterEndpoint.endsWith('v1/vnfs')) {
187                                         vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, (vnfAdapterEndpoint.length()-'/vnfs'.length()))
188                                 }
189                                 vnfAdapterUrl = vnfAdapterEndpoint + '/volume-groups'
190
191                         } else if ('updateVolumeGroupRequest'.equals(requestType)) {
192                                 String volumeGroupId = getChildText(root, 'volumeGroupId')
193
194                                 if (volumeGroupId == null || volumeGroupId.isEmpty()) {
195                                         String msg = getProcessKey(execution) + ': no volumeGroupId in ' + requestType
196                                         logError(msg)
197                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
198                                 }
199
200                                 vnfAdapterMethod = 'PUT'
201                                 if (vnfAdapterEndpoint.endsWith('v1/vnfs')) {
202                                         vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, (vnfAdapterEndpoint.length()-'/vnfs'.length()))
203                                 }
204                                 vnfAdapterUrl = vnfAdapterEndpoint + '/volume-groups/' + URLEncoder.encode(volumeGroupId, 'UTF-8')
205
206                         } else if ('deleteVolumeGroupRequest'.equals(requestType)) {
207                                 String volumeGroupId = getChildText(root, 'volumeGroupId')
208
209                                 if (volumeGroupId == null || volumeGroupId.isEmpty()) {
210                                         String msg = getProcessKey(execution) + ': no volumeGroupId in ' + requestType
211                                         logError(msg)
212                                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
213                                 }
214
215                                 vnfAdapterMethod = 'DELETE'
216                                 if (vnfAdapterEndpoint.endsWith('v1/vnfs')) {
217                                         vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, (vnfAdapterEndpoint.length()-'/vnfs'.length()))
218                                 }
219                                 vnfAdapterUrl = vnfAdapterEndpoint + '/volume-groups/' + URLEncoder.encode(volumeGroupId, 'UTF-8')
220
221                         } else if ('rollbackVolumeGroupRequest'.equals(requestType)) {
222                                 String volumeGroupId = getChildText(root, 'volumeGroupId')
223
224                                 if (volumeGroupId == null || volumeGroupId.isEmpty()) {
225                                         String msg = getProcessKey(execution) + ': no volumeGroupId in ' + requestType
226                                         logError(msg)
227                                         createWorkflowException(execution, 2000, msg)
228                                 }
229
230                                 vnfAdapterMethod = 'DELETE'
231                                 if (vnfAdapterEndpoint.endsWith('v1/vnfs')) {
232                                         vnfAdapterEndpoint = vnfAdapterEndpoint.substring(0, (vnfAdapterEndpoint.length()-'/vnfs'.length()))
233                                 }
234                                 vnfAdapterUrl = vnfAdapterEndpoint + '/volume-groups/' + URLEncoder.encode(volumeGroupId, 'UTF-8')  + '/rollback'
235
236                         } else {
237                                 String msg = getProcessKey(execution) + ': Unsupported request type: ' + requestType
238                                 logError(msg)
239                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
240                         }
241
242                         execution.setVariable(prefix + 'vnfAdapterMethod', vnfAdapterMethod)
243                         logDebug(getProcessKey(execution) + ': ' + prefix + 'vnfAdapterMethod = ' + vnfAdapterMethod, isDebugLogEnabled)
244                         execution.setVariable(prefix + 'vnfAdapterUrl', vnfAdapterUrl)
245                         logDebug(getProcessKey(execution) + ': ' + prefix + 'vnfAdapterUrl = ' + vnfAdapterUrl, isDebugLogEnabled)
246                         execution.setVariable(prefix + 'vnfAdapterRequest', vnfAdapterRequest)
247                         logDebug(getProcessKey(execution) + ': ' + prefix + 'vnfAdapterRequest = \n' + vnfAdapterRequest, isDebugLogEnabled)
248
249                         // Get the Basic Auth credentials for the VnfAdapter
250
251                         String basicAuthValue = execution.getVariable("URN_mso_adapters_po_auth")
252
253                         if (basicAuthValue == null || basicAuthValue.isEmpty()) {
254                                 logError(getProcessKey(execution) + ": mso:adapters:po:auth URN mapping is not defined")
255                         } else {
256                                 logDebug(getProcessKey(execution) + ": Obtained BasicAuth credentials for VnfAdapter:" +
257                                         basicAuthValue, isDebugLogEnabled)
258                                 try {
259                                         def encodedString = utils.getBasicAuth(basicAuthValue, execution.getVariable("URN_mso_msoKey"))
260                                         execution.setVariable(prefix + 'basicAuthHeaderValue', encodedString)
261                                 } catch (IOException ex) {
262                                         logError(getProcessKey(execution) + ": Unable to encode BasicAuth credentials for VnfAdapter")
263                                 }
264                         }
265
266                 } catch (BpmnError e) {
267                         logDebug(" Rethrowing MSOWorkflowException", isDebugLogEnabled)
268                         throw e
269                 } catch (Exception e) {
270                         String msg = 'Caught exception in ' + method + ": " + e
271                         logError(msg)
272                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
273                 }
274         }
275
276         /**
277          * This method is used instead of an HTTP Connector task because the
278          * connector does not allow DELETE with a body.
279          */
280         public void sendRequestToVnfAdapter(Execution execution) {
281                 def method = getClass().getSimpleName() + '.sendRequestToVnfAdapter(' +
282                         'execution=' + execution.getId() +
283                         ')'
284                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
285                 logDebug('Entered ' + method, isDebugLogEnabled)
286
287                 String prefix = execution.getVariable('prefix')
288
289                 try {
290                         String vnfAdapterMethod = execution.getVariable(prefix + 'vnfAdapterMethod')
291                         String vnfAdapterUrl = execution.getVariable(prefix + 'vnfAdapterUrl')
292                         String vnfAdapterRequest = execution.getVariable(prefix + 'vnfAdapterRequest')
293
294                         RESTConfig config = new RESTConfig(vnfAdapterUrl)
295                         RESTClient client = new RESTClient(config).
296                                 addHeader("Content-Type", "application/xml").
297                                 addAuthorizationHeader(execution.getVariable(prefix + "basicAuthHeaderValue"));
298
299                         APIResponse response;
300
301                         if ("GET".equals(vnfAdapterMethod)) {
302                                 response = client.httpGet()
303                         } else if ("PUT".equals(vnfAdapterMethod)) {
304                                 response = client.httpPut(vnfAdapterRequest)
305                         } else if ("POST".equals(vnfAdapterMethod)) {
306                                 response = client.httpPost(vnfAdapterRequest)
307                         } else if ("DELETE".equals(vnfAdapterMethod)) {
308                                 response = client.httpDelete(vnfAdapterRequest)
309                         } else {
310                                 String msg = 'Unsupported HTTP method "' + vnfAdapterMethod + '" in ' + method + ": " + e
311                                 logError(msg)
312                                 exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
313                         }
314
315                         execution.setVariable(prefix + "vnfAdapterStatusCode", response.getStatusCode())
316                         execution.setVariable(prefix + "vnfAdapterResponse", response.getResponseBodyAsString())
317                 } catch (BpmnError e) {
318                         throw e
319                 } catch (Exception e) {
320                         String msg = 'Caught exception in ' + method + ": " + e
321                         logError(msg)
322                         exceptionUtil.buildAndThrowWorkflowException(execution, 2000, msg)
323                 }
324         }
325
326         public void processCallback(Execution execution){
327                 def method = getClass().getSimpleName() + '.processCallback(' +
328                         'execution=' + execution.getId() +
329                         ')'
330                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
331                 logDebug('Entered ' + method, isDebugLogEnabled)
332
333                 String callback = execution.getVariable('VNFAResponse_MESSAGE')
334
335                 try {
336                         logDebug(getProcessKey(execution) + ": received callback:\n" + callback, isDebugLogEnabled)
337
338                         // The XML callback is available to the calling flow in any case,
339                         // even if a WorkflowException is generated.
340                         execution.setVariable(getProcessKey(execution) + 'Response', callback)
341                         // TODO: Should deprecate use of processKey+Response variable for the response. Will use "WorkflowResponse" instead.
342                         execution.setVariable("WorkflowResponse", callback)
343
344                         Node root = new XmlParser().parseText(callback)
345                         if (root.name().endsWith('Exception')) {
346                                 vnfAdapterWorkflowException(execution, callback)
347                         }
348                 } catch (Exception e) {
349                         e.printStackTrace()
350                         callback = callback == null || String.valueOf(callback).isEmpty() ? "NONE" : callback
351                         String msg = "Received error from VnfAdapter: " + callback
352                         logDebug(getProcessKey(execution) + ': ' + msg, isDebugLogEnabled)
353                         exceptionUtil.buildWorkflowException(execution, 7020, msg)
354                 }
355         }
356
357         /**
358          * Tries to parse the response as XML to extract the information to create
359          * a WorkflowException.  If the response cannot be parsed, a more generic
360          * WorkflowException is created.
361          */
362         public void vnfAdapterWorkflowException(Execution execution, Object response) {
363                 try {
364                         Node root = new XmlParser().parseText(response)
365                         String category = getChildText(root, "category")
366                         category = category == null || category.isEmpty() ? "" : " category='" + category + "'"
367                         String message = getChildText(root, "message")
368                         message = message == null || message.isEmpty() ? "" : " message='" + message + "'"
369                         String rolledBack = getChildText(root, "rolledBack")
370                         rolledBack = rolledBack == null || rolledBack.isEmpty() ? "" : " rolledBack='" + rolledBack + "'"
371                         exceptionUtil.buildWorkflowException(execution, 7020, "Received " + root.name() +
372                                 " from VnfAdapter:" + category + message + rolledBack);
373                 } catch (Exception e) {
374                         response = response == null || String.valueOf(response).isEmpty() ? "NONE" : response
375                         exceptionUtil.buildWorkflowException(execution, 7020, "Received error from VnfAdapter: " + response)
376                 }
377         }
378
379         /**
380          * Gets the named child of the specified node.
381          * @param node the node
382          * @param name the child name
383          * @return the child node, or null if no such child exists
384          */
385         private Node getChild(Node node, String name) {
386                 for (Node child : node.children()) {
387                         if (child.name() == name) {
388                                 return child
389                         }
390                 }
391                 return null
392         }
393
394         /**
395          * Gets the text of the named child of the specified node.
396          * @param node the node
397          * @param name the child name
398          * @return the child node text, or null if no such child exists
399          */
400         private String getChildText(Node node, String name) {
401                 Node child = getChild(node, name)
402                 return child == null ? null : child.text()
403         }
404 }