Initial OpenECOMP MSO commit
[so.git] / bpmn / MSOGammaBPMN / src / main / groovy / com / att / bpm / scripts / UpdateAAIGenericVnf.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 com.att.bpm.scripts
22
23 import groovy.util.Node
24 import groovy.util.XmlParser;
25 import groovy.xml.QName
26
27 import java.io.Serializable;
28
29 import org.camunda.bpm.engine.delegate.BpmnError
30 import org.camunda.bpm.engine.runtime.Execution
31 import org.springframework.web.util.UriUtils
32
33 import org.openecomp.mso.rest.APIResponse
34 import org.openecomp.mso.rest.RESTClient
35 import org.openecomp.mso.rest.RESTConfig
36 import org.openecomp.mso.bpmn.core.RollbackData
37 import org.openecomp.mso.bpmn.core.WorkflowException
38
39
40 public class UpdateAAIGenericVnf extends AbstractServiceTaskProcessor {
41
42         private XmlParser xmlParser = new XmlParser()
43
44         /**
45          * Initialize the flow's variables.
46          *
47          * @param execution The flow's execution instance.
48          */
49         public void initProcessVariables(Execution execution) {
50                 execution.setVariable('prefix', 'UAAIGenVnf_')
51                 execution.setVariable('UAAIGenVnf_vnfId', null)
52                 execution.setVariable('UAAIGenVnf_personaModelId', null)
53                 execution.setVariable('UAAIGenVnf_personaModelVersion', null)
54                 execution.setVariable('UAAIGenVnf_getGenericVnfResponseCode' ,null)
55                 execution.setVariable('UAAIGenVnf_getGenericVnfResponse', '')
56                 execution.setVariable('UAAIGenVnf_updateGenericVnfResponseCode', null)
57                 execution.setVariable('UAAIGenVnf_updateGenericVnfResponse', '')
58         }
59
60         /**
61          * Check for missing elements in the received request.
62          *
63          * @param execution The flow's execution instance.
64          */
65         public void preProcessRequest(Execution execution) {
66                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
67                         'execution=' + execution.getId() +
68                         ')'
69                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
70                 logDebug('Entered ' + method, isDebugLogEnabled)
71
72                 try {
73                         def xml = execution.getVariable('UpdateAAIGenericVnfRequest')
74                         logDebug('Received request xml:\n' + xml, isDebugLogEnabled)
75                         initProcessVariables(execution)
76
77                         def vnfId = getRequiredNodeText(execution, xml,'vnf-id')
78                         execution.setVariable('UAAIGenVnf_vnfId', vnfId)
79
80                         def personaModelId = getRequiredNodeText(execution, xml,'persona-model-id')
81                         execution.setVariable('UAAIGenVnf_personaModelId', personaModelId)
82                         
83                         def personaModelVersion = getRequiredNodeText(execution, xml,'persona-model-version')
84                         execution.setVariable('UAAIGenVnf_personaModelVersion', personaModelVersion)
85                         
86                         logDebug('Exited ' + method, isDebugLogEnabled)
87                 } catch (BpmnError e) {
88                         throw e;
89                 } catch (Exception e) {
90                         logError('Caught exception in ' + method, e)
91                         createWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
92                 }
93         }
94
95         /**
96          * Using the received vnfId, query AAI to get the corresponding Generic VNF.
97          * A 200 response is expected with the VF Module in the response body.
98          *
99          * @param execution The flow's execution instance.
100          */
101         public void getGenericVnf(Execution execution) {
102                 def method = getClass().getSimpleName() + '.getGenericVnf(' +
103                         'execution=' + execution.getId() +
104                         ')'
105                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
106                 logDebug('Entered ' + method, isDebugLogEnabled)
107
108                 try {
109                         def vnfId = execution.getVariable('UAAIGenVnf_vnfId')
110
111                         // Construct endpoint
112                         AaiUtil aaiUriUtil = new AaiUtil(this)
113                         def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
114                         logDebug('AAI URI is: ' + aai_uri, isDebugLogEnabled)
115                         String endPoint = execution.getVariable('URN_aai_endpoint') + aai_uri + '/' + UriUtils.encode(vnfId, "UTF-8")
116
117                         String basicAuthCred = utils.getBasicAuth(execution.getVariable("URN_aai_auth"),execution.getVariable("URN_mso_msoKey"))
118
119                         try {
120                                 RESTConfig config = new RESTConfig(endPoint);
121                                 def responseData = ''
122                                 def aaiRequestId = UUID.randomUUID().toString()
123                                 RESTClient client = new RESTClient(config).
124                                         addHeader('X-TransactionId', aaiRequestId).
125                                         addHeader('X-FromAppId', 'MSO').
126                                         addHeader('Content-Type', 'application/xml').
127                                         addHeader('Accept','application/xml');
128                                 if (basicAuthCred != null && !"".equals(basicAuthCred)) {
129                                         client.addAuthorizationHeader(basicAuthCred)
130                                 }
131
132                                 logDebug('sending GET to AAI endpoint \'' + endPoint + '\'', isDebugLogEnabled)
133                                 APIResponse response = client.httpGet()
134
135                                 responseData = response.getResponseBodyAsString()
136                                 execution.setVariable('UAAIGenVnf_getGenericVnfResponseCode', response.getStatusCode())
137                                 execution.setVariable('UAAIGenVnf_getGenericVnfResponse', responseData)
138                                 logDebug('Response code:' + response.getStatusCode(), isDebugLogEnabled)
139                                 logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
140                         } catch (Exception ex) {
141                                 ex.printStackTrace()
142                                 logDebug('Exception occurred while executing AAI GET:' + ex.getMessage(),isDebugLogEnabled)
143                                 execution.setVariable('UAAIGenVnf_getGenericVnfResponseCode', 500)
144                                 execution.setVariable('UAAIGenVnf_getGenericVnfResponse', 'AAI GET Failed:' + ex.getMessage())
145                         }
146                         logDebug('Exited ' + method, isDebugLogEnabled)
147                 } catch (BpmnError e) {
148                         throw e;
149                 } catch (Exception e) {
150                         logError('Caught exception in ' + method, e)
151                         createWorkflowException(execution, 1002, 'Error in getGenericVnf(): ' + e.getMessage())
152                 }
153         }
154
155         /**
156          * Construct and send a PUT request to AAI to update the Generic VNF.
157          *
158          * @param execution The flow's execution instance.
159          */
160         public void updateGenericVnf(Execution execution) {
161                 def method = getClass().getSimpleName() + '.updateGenericVnf(' +
162                         'execution=' + execution.getId() +
163                         ')'
164                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
165                 logDebug('Entered ' + method, isDebugLogEnabled)
166
167                 try {
168                         def vnfId = execution.getVariable('UAAIGenVnf_vnfId')
169                         def genericVnf = execution.getVariable('UAAIGenVnf_getGenericVnfResponse')
170                         def origRequest = execution.getVariable('UpdateAAIGenericVnfRequest')
171                         
172                         // Confirm resource-version is in retrieved Generic VNF
173                         def Node genericVnfNode = xmlParser.parseText(genericVnf)
174                         if (utils.getChildNode(genericVnfNode, 'resource-version') == null) {
175                                 def msg = 'Can\'t update Generic VNF ' + vnfId + ' since \'resource-version\' is missing'
176                                 logError(msg)
177                                 throw new Exception(msg)
178                         }
179                         
180                         // Handle persona-model-id/persona-model-version
181                         def String newPersonaModelId = execution.getVariable('UAAIGenVnf_personaModelId')
182                         def String newPersonaModelVersion = execution.getVariable('UAAIGenVnf_personaModelVersion')
183                         
184                         // Confirm "new" persona-model-id is same as "current" persona-model-id
185                         def Node currPersonaModelIdNode = utils.getChildNode(genericVnfNode, 'persona-model-id')
186                         def String currPersonaModelId = ''
187                         if (currPersonaModelIdNode != null) {
188                                 currPersonaModelId = currPersonaModelIdNode.text()
189                         }
190                         if (!newPersonaModelId.equals(currPersonaModelId)) {
191                                 def msg = 'Can\'t update Generic VNF ' + vnfId + ' since there is \'persona-model-id\' mismatch between the current and new values'
192                                 logError(msg)
193                                 throw new Exception(msg)
194                         }
195                         
196                         // Construct payload
197                         updateGenericVnfNode(origRequest, genericVnfNode, 'persona-model-version')
198                         def payload = utils.nodeToString(genericVnfNode)
199
200                         // Construct endpoint
201                         AaiUtil aaiUriUtil = new AaiUtil(this)
202                         def aai_uri = aaiUriUtil.getNetworkGenericVnfUri(execution)
203                         logDebug('AAI URI is: ' + aai_uri, isDebugLogEnabled)
204                         String endPoint = execution.getVariable('URN_aai_endpoint') + aai_uri + '/' + UriUtils.encode(vnfId, "UTF-8")
205
206                         String basicAuthCred = utils.getBasicAuth(execution.getVariable("URN_aai_auth"),execution.getVariable("URN_mso_msoKey"))
207
208                         try {
209                                 RESTConfig config = new RESTConfig(endPoint);
210                                 def responseData = ''
211                                 def aaiRequestId = UUID.randomUUID().toString()
212                                 RESTClient client = new RESTClient(config).
213                                         addHeader('X-TransactionId', aaiRequestId).
214                                         addHeader('X-FromAppId', 'MSO').
215                                         addHeader('Content-Type', 'application/xml').
216                                         addHeader('Accept','application/xml');
217                                 if (basicAuthCred != null && !"".equals(basicAuthCred)) {
218                                         client.addAuthorizationHeader(basicAuthCred)
219                                 }
220
221                                 logDebug('sending PUT to AAI endpoint \'' + endPoint + '\'' + 'with payload \n' + payload, isDebugLogEnabled)
222                                 APIResponse response = client.httpPut(payload)
223
224                                 responseData = response.getResponseBodyAsString()
225                                 execution.setVariable('UAAIGenVnf_updateGenericVnfResponseCode', response.getStatusCode())
226                                 execution.setVariable('UAAIGenVnf_updateGenericVnfResponse', responseData)
227                                 logDebug('Response code:' + response.getStatusCode(), isDebugLogEnabled)
228                                 logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
229                         } catch (Exception ex) {
230                                 ex.printStackTrace()
231                                 logDebug('Exception occurred while executing AAI PUT:' + ex.getMessage(),isDebugLogEnabled)
232                                 execution.setVariable('UAAIGenVnf_updateGenericVnfResponseCode', 500)
233                                 execution.setVariable('UAAIGenVnf_updateGenericVnfResponse', 'AAI PUT Failed:' + ex.getMessage())
234                         }
235                         logDebug('Exited ' + method, isDebugLogEnabled)
236                 } catch (BpmnError e) {
237                         throw e;
238                 } catch (Exception e) {
239                         logError('Caught exception in ' + method, e)
240                         createWorkflowException(execution, 1002, 'Error in updateGenericVnf(): ' + e.getMessage())
241                 }
242         }
243
244         /**
245          * Insert a new Node, replace the value of an existing Node, or delete an existing Node in the current
246          * Generic VNF Node, as necessary.
247          *
248          * If the Node with the same name already exists in current Generic VNF, but is not being updated, then do
249          * nothing. If the element is being updated and it already exists in the current Generic VNF, then check
250          * the value specified in the original request. If the value is 'DELETE', remove that Node from the
251          * current Generic VNF.  Otherwise, change the value to the specified new value. If the element is
252          * being updated but doesn't exist in the current Generic VNF, and the new value is not 'DELETE', then
253          * create an appropriate new node and add it to the Generic VNF.
254          *
255          * @param origRequest Incoming update request with Generic VNF element(s) to be updated.
256          * @param genericVnf Current Generic VNF retrieved from AAI.
257          * @param element Name of element to be inserted.
258          */
259         public void updateGenericVnfNode(String origRequest, Node genericVnfNode, String elementName) {
260
261                 if (!utils.nodeExists(origRequest, elementName)) {
262                         return
263                 }
264                 def elementValue = utils.getNodeText(origRequest, elementName)
265
266                 def Node childNode = utils.getChildNode(genericVnfNode, elementName)
267                 if (childNode == null) {
268                         if (elementValue.equals('DELETE')) {
269                                 // Element doesn't exist but is being deleted, so do nothing
270                                 return
271                         }
272                         // Node doesn't exist, create a new Node as a child
273                         new Node(genericVnfNode, elementName, elementValue)
274                 } else {
275                         if (elementValue.equals('DELETE')) {
276                                 // Node exists, but should be deleted
277                                 genericVnfNode.remove(childNode)
278                         } else {
279                                 // Node already exists, just give it a new value
280                                 childNode.setValue(elementValue)
281                         }
282                 }
283         }
284
285         /**
286          * Generates a WorkflowException if the AAI query returns a response code other than 200.
287          *
288          * @param execution The flow's execution instance.
289          */
290         public void handleAAIQueryFailure(Execution execution) {
291                 def method = getClass().getSimpleName() + '.handleAAIQueryFailure(' +
292                         'execution=' + execution.getId() +
293                         ')'
294                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
295                 logDebug('Entered ' + method, isDebugLogEnabled)
296
297                 logError('Error occurred attempting to query AAI, Response Code ' +
298                         execution.getVariable('UAAIGenVnf_getGenericVnfResponseCode') + ', Error Response ' +
299                         execution.getVariable('UAAIGenVnf_getGenericVnfResponse'))
300                 String processKey = getProcessKey(execution);
301                 WorkflowException exception = new WorkflowException(processKey, 5000,
302                         execution.getVariable('UAAIGenVnf_getGenericVnfResponse'))
303                 execution.setVariable('WorkflowException', exception)
304
305                 logDebug('Exited ' + method, isDebugLogEnabled)
306         }
307
308         /**
309          * Generates a WorkflowException if updating a VF Module in AAI returns a response code other than 200.
310          *
311          * @param execution The flow's execution instance.
312          */
313         public void handleUpdateGenericVnfFailure(Execution execution) {
314                 def method = getClass().getSimpleName() + '.handleUpdateGenericVnfFailure(' +
315                         'execution=' + execution.getId() +
316                         ')'
317                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
318                 logDebug('Entered ' + method, isDebugLogEnabled)
319
320                 logError('Error occurred attempting to update Generic VNF in AAI, Response Code ' +
321                         execution.getVariable('UAAIGenVnf_updateGenericVnfResponseCode') + ', Error Response ' +
322                         execution.getVariable('UAAIGenVnf_updateGenericVnfResponse'))
323                 String processKey = getProcessKey(execution);
324                 WorkflowException exception = new WorkflowException(processKey, 5000,
325                         execution.getVariable('UAAIGenVnf_updateGenericVnfResponse'))
326                 execution.setVariable('WorkflowException', exception)
327
328                 logDebug('Exited ' + method, isDebugLogEnabled)
329         }
330 }