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