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