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