31da330c7fd0829646ca86517cf1b23256fad32a
[so.git] / adapters / mso-openstack-adapters / src / main / java / org / onap / so / adapters / tasks / orchestration / PollService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017-2019 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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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=========================================================
21  */
22
23 package org.onap.so.adapters.tasks.orchestration;
24
25 import java.io.ByteArrayInputStream;
26 import java.io.StringReader;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Optional;
30 import javax.xml.bind.JAXB;
31 import javax.xml.parsers.DocumentBuilder;
32 import javax.xml.parsers.DocumentBuilderFactory;
33 import org.apache.commons.lang3.mutable.MutableBoolean;
34 import org.camunda.bpm.client.task.ExternalTask;
35 import org.camunda.bpm.client.task.ExternalTaskService;
36 import org.onap.so.adapters.network.MsoNetworkAdapterImpl;
37 import org.onap.so.adapters.nwrest.CreateNetworkRequest;
38 import org.onap.so.adapters.nwrest.CreateNetworkResponse;
39 import org.onap.so.adapters.nwrest.DeleteNetworkRequest;
40 import org.onap.so.adapters.nwrest.DeleteNetworkResponse;
41 import org.onap.so.adapters.nwrest.RollbackNetworkRequest;
42 import org.onap.so.adapters.nwrest.UpdateNetworkRequest;
43 import org.onap.so.adapters.nwrest.UpdateNetworkResponse;
44 import org.onap.so.adapters.vnf.MsoVnfAdapterImpl;
45 import org.onap.so.adapters.vnf.VnfAdapterUtils;
46 import org.onap.so.adapters.vnfrest.CreateVfModuleRequest;
47 import org.onap.so.adapters.vnfrest.CreateVfModuleResponse;
48 import org.onap.so.adapters.vnfrest.CreateVolumeGroupRequest;
49 import org.onap.so.adapters.vnfrest.CreateVolumeGroupResponse;
50 import org.onap.so.adapters.vnfrest.DeleteVfModuleRequest;
51 import org.onap.so.adapters.vnfrest.DeleteVfModuleResponse;
52 import org.onap.so.adapters.vnfrest.DeleteVolumeGroupRequest;
53 import org.onap.so.adapters.vnfrest.DeleteVolumeGroupResponse;
54 import org.onap.so.adapters.vnfrest.VfModuleRollback;
55 import org.onap.so.adapters.vnfrest.VolumeGroupRollback;
56 import org.onap.so.logging.tasks.AuditMDCSetup;
57 import org.onap.so.openstack.beans.NetworkRollback;
58 import org.onap.so.openstack.beans.StackInfo;
59 import org.onap.so.openstack.beans.VnfRollback;
60 import org.onap.so.openstack.exceptions.MsoException;
61 import org.onap.so.openstack.mappers.StackInfoMapper;
62 import org.onap.so.openstack.utils.MsoHeatUtils;
63 import org.onap.so.utils.ExternalTaskUtils;
64 import org.onap.so.utils.RetrySequenceLevel;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67 import org.springframework.beans.factory.annotation.Autowired;
68 import org.springframework.stereotype.Component;
69 import com.woorea.openstack.heat.model.Stack;
70
71 @Component
72 public class PollService extends ExternalTaskUtils {
73
74     private static final Logger logger = LoggerFactory.getLogger(PollService.class);
75
76     @Autowired
77     private MsoVnfAdapterImpl vnfAdapterImpl;
78
79     @Autowired
80     private MsoNetworkAdapterImpl networkAdapterImpl;
81
82     @Autowired
83     private MsoHeatUtils msoHeatUtils;
84
85     @Autowired
86     private VnfAdapterUtils vnfAdapterUtils;
87
88     @Autowired
89     private AuditMDCSetup mdcSetup;
90
91     public PollService() {
92         super(RetrySequenceLevel.SHORT);
93     }
94
95     public void executeExternalTask(ExternalTask externalTask, ExternalTaskService externalTaskService) {
96         mdcSetup.setupMDC(externalTask);
97         logger.debug("Starting External Task Poll Service");
98         Map<String, Object> variables = new HashMap<>();
99         MutableBoolean success = new MutableBoolean();
100         String errorMessage = null;
101         Optional<String> response = Optional.empty();
102         boolean isMulticloud = false;
103         try {
104             String xmlRequest = externalTask.getVariable("openstackAdapterTaskRequest");
105             if (xmlRequest != null) {
106                 Optional<String> requestType = findRequestType(xmlRequest);
107                 if ("createVolumeGroupRequest".equals(requestType.get())) {
108                     CreateVolumeGroupRequest req =
109                             JAXB.unmarshal(new StringReader(xmlRequest), CreateVolumeGroupRequest.class);
110                     isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
111                     response = determineCreateVolumeGroupStatus(req, externalTask, success, isMulticloud);
112                 } else if ("createVfModuleRequest".equals(requestType.get())) {
113                     CreateVfModuleRequest req =
114                             JAXB.unmarshal(new StringReader(xmlRequest), CreateVfModuleRequest.class);
115                     isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
116                     response = determineCreateVfModuleStatus(req, externalTask, success, isMulticloud);
117                 } else if ("deleteVfModuleRequest".equals(requestType.get())) {
118                     logger.debug("Executing External Task Poll Service for Delete Vf Module");
119                     String stackId = externalTask.getVariable("stackId");
120                     DeleteVfModuleRequest req =
121                             JAXB.unmarshal(new StringReader(xmlRequest), DeleteVfModuleRequest.class);
122                     isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
123                     if (!isMulticloud) {
124                         int timeoutMinutes = msoHeatUtils.getVfHeatTimeoutValue(req.getModelCustomizationUuid(), false);
125                         StackInfo stack = pollDeleteResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(),
126                                 stackId, success);
127                         DeleteVfModuleResponse deleteResponse =
128                                 new DeleteVfModuleResponse(req.getVnfId(), req.getVfModuleId(), Boolean.TRUE,
129                                         req.getMessageId(), vnfAdapterImpl.copyStringOutputs(stack.getOutputs()));
130                         response = Optional.of(deleteResponse.toXmlString());
131                     }
132                 } else if ("deleteVolumeGroupRequest".equals(requestType.get())) {
133                     logger.debug("Executing External Task Poll Service for Delete Volume Group");
134                     String stackId = externalTask.getVariable("stackId");
135                     DeleteVolumeGroupRequest req =
136                             JAXB.unmarshal(new StringReader(xmlRequest), DeleteVolumeGroupRequest.class);
137                     isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
138                     if (!isMulticloud) {
139                         pollDeleteResource(118, req.getCloudSiteId(), req.getTenantId(), stackId, success);
140                         DeleteVolumeGroupResponse deleteResponse =
141                                 new DeleteVolumeGroupResponse(true, req.getMessageId());
142                         response = Optional.of(deleteResponse.toXmlString());
143                     }
144                 } else if ("createNetworkRequest".equals(requestType.get())) {
145                     CreateNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), CreateNetworkRequest.class);
146                     response = determineCreateNetworkStatus(req, externalTask, success);
147                 } else if ("deleteNetworkRequest".equals(requestType.get())) {
148                     logger.debug("Executing External Task Poll Service for Delete Network");
149                     String stackId = externalTask.getVariable("stackId");
150                     DeleteNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), DeleteNetworkRequest.class);
151                     pollDeleteResource(118, req.getCloudSiteId(), req.getTenantId(), stackId, success);
152                     DeleteNetworkResponse deleteResponse =
153                             new DeleteNetworkResponse(req.getNetworkId(), true, req.getMessageId());
154                     response = Optional.of(deleteResponse.toXmlString());
155                 } else if ("updateNetworkRequest".equals(requestType.get())) {
156                     UpdateNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), UpdateNetworkRequest.class);
157                     pollUpdateResource(req.getCloudSiteId(), req.getTenantId(), externalTask, success);
158                     UpdateNetworkResponse updateResponse =
159                             new UpdateNetworkResponse(req.getNetworkId(), null, null, req.getMessageId());
160                     response = Optional.of(updateResponse.toXmlString());
161                 } else if ("rollbackNetworkRequest".equals(requestType.get())) {
162                     logger.debug("Executing External Task Poll Service for Rollback Network");
163                     String stackId = externalTask.getVariable("stackId");
164                     RollbackNetworkRequest req =
165                             JAXB.unmarshal(new StringReader(xmlRequest), RollbackNetworkRequest.class);
166                     pollDeleteResource(118, req.getNetworkRollback().getCloudId(),
167                             req.getNetworkRollback().getTenantId(), stackId, success);
168                 }
169             }
170         } catch (Exception e) {
171             logger.error("Error during External Task Poll Service", e);
172             errorMessage = e.toString();
173             variables.put("openstackAdapterErrorMessage", errorMessage);
174         }
175
176         if (isMulticloud) {
177             success.setTrue();
178         }
179         if (response.isPresent()) {
180             variables.put("WorkflowResponse", response.get());
181         }
182         variables.put("OpenstackPollSuccess", success.booleanValue());
183         if (success.isTrue()) {
184             externalTaskService.complete(externalTask, variables);
185             logger.debug("The External Task Id: {}  Successful", externalTask.getId());
186         } else {
187             if (externalTask.getRetries() == null) {
188                 logger.debug("The External Task Id: {}  Failed, Setting Retries to Default Start Value: {}",
189                         externalTask.getId(), getRetrySequence().length);
190                 externalTaskService.handleFailure(externalTask, "errorMessage", "errorDetails",
191                         getRetrySequence().length, 10000);
192             } else if (externalTask.getRetries() != null && externalTask.getRetries() - 1 == 0) {
193                 logger.debug("The External Task Id: {}  Failed, All Retries Exhausted", externalTask.getId());
194                 externalTaskService.complete(externalTask, variables);
195             } else {
196                 logger.debug("The External Task Id: {}  Failed, Decrementing Retries: {} , Retry Delay: {}",
197                         externalTask.getId(), externalTask.getRetries() - 1,
198                         calculateRetryDelay(externalTask.getRetries()));
199                 externalTaskService.handleFailure(externalTask, "errorMessage", "errorDetails",
200                         externalTask.getRetries() - 1, calculateRetryDelay(externalTask.getRetries()));
201             }
202         }
203     }
204
205     private Optional<String> determineCreateVolumeGroupStatus(CreateVolumeGroupRequest req, ExternalTask externalTask,
206             MutableBoolean success, boolean isMulticloud) throws MsoException {
207         boolean pollRollbackStatus = externalTask.getVariable("PollRollbackStatus");
208         String stackId = externalTask.getVariable("stackId");
209         if (pollRollbackStatus) {
210             logger.debug("Executing External Task Poll Service for Rollback Volume Group");
211             if (!isMulticloud) {
212                 pollDeleteResource(118, req.getCloudSiteId(), req.getTenantId(), stackId, success);
213             }
214             return Optional.empty();
215         } else {
216             logger.debug("Executing External Task Poll Service for Create Volume Group");
217             Map<String, String> outputs = new HashMap<String, String>();
218             if (!isMulticloud) {
219                 int timeoutMinutes = msoHeatUtils.getVfHeatTimeoutValue(req.getModelCustomizationUuid(), true);
220                 StackInfo stack =
221                         pollCreateResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
222                 outputs = vnfAdapterImpl.copyStringOutputs(stack.getOutputs());
223             }
224             VolumeGroupRollback rb = new VolumeGroupRollback(req.getVolumeGroupId(), stackId, true, req.getTenantId(),
225                     req.getCloudOwner(), req.getCloudSiteId(), req.getMsoRequest(), req.getMessageId());
226             CreateVolumeGroupResponse createResponse = new CreateVolumeGroupResponse(req.getVolumeGroupId(), stackId,
227                     true, outputs, rb, req.getMessageId());
228             return Optional.of(createResponse.toXmlString());
229         }
230     }
231
232     private Optional<String> determineCreateVfModuleStatus(CreateVfModuleRequest req, ExternalTask externalTask,
233             MutableBoolean success, boolean isMulticloud) throws MsoException {
234         String stackId = externalTask.getVariable("stackId");
235         boolean pollRollbackStatus = externalTask.getVariable("PollRollbackStatus");
236         int timeoutMinutes = msoHeatUtils.getVfHeatTimeoutValue(req.getModelCustomizationUuid(), false);
237         if (pollRollbackStatus) {
238             logger.debug("Executing External Task Poll Service for Rollback Vf Module");
239             if (!isMulticloud) {
240                 pollDeleteResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
241             }
242             return Optional.empty();
243         } else {
244             logger.debug("Executing External Task Poll Service for Create Vf Module");
245             Map<String, String> outputs = new HashMap<String, String>();
246             if (!isMulticloud) {
247                 StackInfo stack =
248                         pollCreateResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
249                 outputs = vnfAdapterImpl.copyStringOutputs(stack.getOutputs());
250
251             }
252             VfModuleRollback modRollback = new VfModuleRollback(buildVnfRollback(req, stackId, isMulticloud),
253                     req.getVfModuleId(), stackId, req.getMessageId());
254             CreateVfModuleResponse createResponse = new CreateVfModuleResponse(req.getVnfId(), req.getVfModuleId(),
255                     stackId, Boolean.TRUE, outputs, modRollback, req.getMessageId());
256             return Optional.of(createResponse.toXmlString());
257         }
258     }
259
260     private Optional<String> determineCreateNetworkStatus(CreateNetworkRequest req, ExternalTask externalTask,
261             MutableBoolean success) throws MsoException {
262         String stackId = externalTask.getVariable("stackId");
263         boolean pollRollbackStatus = externalTask.getVariable("PollRollbackStatus");
264         int timeoutMinutes =
265                 msoHeatUtils.getNetworkHeatTimeoutValue(req.getModelCustomizationUuid(), req.getNetworkType());
266         if (pollRollbackStatus) {
267             logger.debug("Executing External Task Poll Service for Rollback Network");
268             pollDeleteResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
269             return Optional.empty();
270         } else {
271             logger.debug("Executing External Task Poll Service for Create Network");
272             boolean os3Nw = externalTask.getVariable("os3Nw");
273             StackInfo stack =
274                     pollCreateResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
275             String networkFqdn = "";
276             String neutronNetworkId = "";
277             Map<String, String> subnetMap = new HashMap<>();
278             if (stack.getOutputs() != null) {
279                 networkFqdn = (String) stack.getOutputs().get("network_fqdn");
280                 neutronNetworkId = (String) stack.getOutputs().get("network_id");
281                 subnetMap = networkAdapterImpl.buildSubnetMap(stack.getOutputs(), req.getSubnets(), os3Nw);
282             }
283             CreateNetworkResponse response = new CreateNetworkResponse(req.getNetworkId(), neutronNetworkId, stackId,
284                     networkFqdn, true, subnetMap, buildNetworkRollback(req, stackId), req.getMessageId());
285             return Optional.of(response.toXmlString());
286
287         }
288     }
289
290     private StackInfo pollCreateResource(int pollingTimeout, String cloudSiteId, String tenantId, String stackId,
291             MutableBoolean success) throws MsoException {
292         Stack currentStack = createCurrentStack(stackId);
293         Stack stack = msoHeatUtils.pollStackForStatus(pollingTimeout, currentStack, "CREATE_IN_PROGRESS", cloudSiteId,
294                 tenantId, false);
295         msoHeatUtils.postProcessStackCreate(stack, false, 0, false, cloudSiteId, tenantId, null);
296         success.setTrue();
297         return new StackInfoMapper(stack).map();
298     }
299
300     private StackInfo pollDeleteResource(int pollingTimeout, String cloudSiteId, String tenantId, String stackId,
301             MutableBoolean success) throws MsoException {
302         Stack currentStack = createCurrentStack(stackId);
303         Stack stack = msoHeatUtils.pollStackForStatus(pollingTimeout, currentStack, "DELETE_IN_PROGRESS", cloudSiteId,
304                 tenantId, true);
305         if (stack != null) { // if stack is null it was not found and no need to do post process
306             msoHeatUtils.postProcessStackDelete(stack);
307         }
308         success.setTrue();
309         return new StackInfoMapper(stack).map();
310     }
311
312     private void pollUpdateResource(String cloudSiteId, String tenantId, ExternalTask externalTask,
313             MutableBoolean success) throws MsoException {
314         Stack currentStack = createCurrentStack(externalTask.getVariable("stackId"));
315         Stack stack =
316                 msoHeatUtils.pollStackForStatus(1, currentStack, "UPDATE_IN_PROGRESS", cloudSiteId, tenantId, false);
317         msoHeatUtils.postProcessStackUpdate(stack);
318         success.setTrue();
319     }
320
321     protected Optional<String> findRequestType(String xmlString) {
322         try {
323             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
324             DocumentBuilder builder = factory.newDocumentBuilder();
325             org.w3c.dom.Document doc;
326             doc = builder.parse(new ByteArrayInputStream(xmlString.getBytes("UTF-8")));
327             return Optional.of(doc.getDocumentElement().getNodeName());
328         } catch (Exception e) {
329             logger.error("Error Finding Request Type", e);
330             return Optional.empty();
331         }
332     }
333
334     private Stack createCurrentStack(String canonicalStackId) {
335         Stack currentStack = new Stack();
336         String stackName = canonicalStackId;
337         if (canonicalStackId.contains("/")) {
338             String[] stacks = canonicalStackId.split("/");
339             stackName = stacks[0];
340             currentStack.setId(stacks[1]);
341         }
342         currentStack.setStackName(stackName);
343         return currentStack;
344     }
345
346     private VnfRollback buildVnfRollback(CreateVfModuleRequest req, String stackId, boolean isMulticloud) {
347         VnfRollback vfRollback = new VnfRollback();
348         vfRollback.setCloudSiteId(req.getCloudSiteId());
349         vfRollback.setCloudOwner(req.getCloudOwner());
350         vfRollback.setTenantId(req.getTenantId());
351         vfRollback.setMsoRequest(req.getMsoRequest());
352         vfRollback.setRequestType(req.getRequestType());
353         vfRollback.setVolumeGroupHeatStackId(req.getVolumeGroupStackId());
354         vfRollback.setBaseGroupHeatStackId(req.getBaseVfModuleStackId());
355         vfRollback.setIsBase(false);
356         vfRollback.setModelCustomizationUuid(req.getModelCustomizationUuid());
357         vfRollback.setVnfId(stackId);
358         vfRollback.setVnfCreated(true);
359         if (isMulticloud) {
360             vfRollback.setMode("CFY");
361         }
362
363         return vfRollback;
364     }
365
366     private NetworkRollback buildNetworkRollback(CreateNetworkRequest req, String stackId) {
367         NetworkRollback networkRollback = new NetworkRollback();
368         networkRollback.setCloudId(req.getCloudSiteId());
369         networkRollback.setTenantId(req.getTenantId());
370         networkRollback.setMsoRequest(req.getMsoRequest());
371         networkRollback.setModelCustomizationUuid(req.getModelCustomizationUuid());
372         networkRollback.setNetworkStackId(stackId);
373         networkRollback.setNetworkCreated(true);
374         networkRollback.setNetworkType(req.getNetworkType());
375
376         return networkRollback;
377     }
378 }