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.util.HashMap;
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.UpdateNetworkRequest;
42 import org.onap.so.adapters.nwrest.UpdateNetworkResponse;
43 import org.onap.so.adapters.vnf.MsoVnfAdapterImpl;
44 import org.onap.so.adapters.vnf.VnfAdapterUtils;
45 import org.onap.so.adapters.vnfrest.CreateVfModuleRequest;
46 import org.onap.so.adapters.vnfrest.CreateVfModuleResponse;
47 import org.onap.so.adapters.vnfrest.CreateVolumeGroupRequest;
48 import org.onap.so.adapters.vnfrest.CreateVolumeGroupResponse;
49 import org.onap.so.adapters.vnfrest.DeleteVfModuleRequest;
50 import org.onap.so.adapters.vnfrest.DeleteVfModuleResponse;
51 import org.onap.so.adapters.vnfrest.DeleteVolumeGroupRequest;
52 import org.onap.so.adapters.vnfrest.DeleteVolumeGroupResponse;
53 import org.onap.so.adapters.vnfrest.VfModuleRollback;
54 import org.onap.so.adapters.vnfrest.VolumeGroupRollback;
55 import org.onap.so.logging.tasks.AuditMDCSetup;
56 import org.onap.so.openstack.beans.NetworkRollback;
57 import org.onap.so.openstack.beans.StackInfo;
58 import org.onap.so.openstack.beans.VnfRollback;
59 import org.onap.so.openstack.exceptions.MsoException;
60 import org.onap.so.openstack.mappers.StackInfoMapper;
61 import org.onap.so.openstack.utils.MsoHeatUtils;
62 import org.onap.so.utils.ExternalTaskUtils;
63 import org.onap.so.utils.RetrySequenceLevel;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66 import org.springframework.beans.factory.annotation.Autowired;
67 import org.springframework.stereotype.Component;
68 import com.woorea.openstack.heat.model.Stack;
71 public class PollService extends ExternalTaskUtils {
73 private static final Logger logger = LoggerFactory.getLogger(PollService.class);
76 private MsoVnfAdapterImpl vnfAdapterImpl;
79 private MsoNetworkAdapterImpl networkAdapterImpl;
82 private MsoHeatUtils msoHeatUtils;
85 private VnfAdapterUtils vnfAdapterUtils;
88 private AuditMDCSetup mdcSetup;
90 public PollService() {
91 super(RetrySequenceLevel.SHORT);
94 public void executeExternalTask(ExternalTask externalTask, ExternalTaskService externalTaskService) {
95 mdcSetup.setupMDC(externalTask);
96 logger.debug("Starting External Task Poll Service");
97 Map<String, Object> variables = new HashMap<>();
98 MutableBoolean success = new MutableBoolean();
99 String errorMessage = null;
100 String response = "";
102 String xmlRequest = externalTask.getVariable("openstackAdapterTaskRequest");
103 if (xmlRequest != null) {
104 Optional<String> requestType = findRequestType(xmlRequest);
105 if ("createVolumeGroupRequest".equals(requestType.get())) {
106 response = determineCreateVolumeGroupStatus(xmlRequest, externalTask, success);
107 } else if ("createVfModuleRequest".equals(requestType.get())) {
108 response = determineCreateVfModuleStatus(xmlRequest, externalTask, success);
109 } else if ("deleteVfModuleRequest".equals(requestType.get())) {
110 logger.debug("Executing External Task Poll Service for Delete Vf Module");
111 String stackId = externalTask.getVariable("stackId");
112 DeleteVfModuleRequest req =
113 JAXB.unmarshal(new StringReader(xmlRequest), DeleteVfModuleRequest.class);
114 boolean isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
116 int timeoutMinutes = msoHeatUtils.getVfHeatTimeoutValue(req.getModelCustomizationUuid(), false);
117 StackInfo stack = pollDeleteResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(),
119 DeleteVfModuleResponse deleteResponse =
120 new DeleteVfModuleResponse(req.getVnfId(), req.getVfModuleId(), Boolean.TRUE,
121 req.getMessageId(), vnfAdapterImpl.copyStringOutputs(stack.getOutputs()));
122 response = deleteResponse.toXmlString();
124 } else if ("deleteVolumeGroupRequest".equals(requestType.get())) {
125 logger.debug("Executing External Task Poll Service for Delete Volume Group");
126 String stackId = externalTask.getVariable("stackId");
127 DeleteVolumeGroupRequest req =
128 JAXB.unmarshal(new StringReader(xmlRequest), DeleteVolumeGroupRequest.class);
129 boolean isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
131 pollDeleteResource(118, req.getCloudSiteId(), req.getTenantId(), stackId, success);
132 DeleteVolumeGroupResponse deleteResponse =
133 new DeleteVolumeGroupResponse(true, req.getMessageId());
134 response = deleteResponse.toXmlString();
138 } else if ("createNetworkRequest".equals(requestType.get())) {
139 response = determineCreateNetworkStatus(xmlRequest, externalTask, success);
140 } else if ("deleteNetworkRequest".equals(requestType.get())) {
141 logger.debug("Executing External Task Poll Service for Delete Network");
142 String stackId = externalTask.getVariable("stackId");
143 DeleteNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), DeleteNetworkRequest.class);
144 pollDeleteResource(118, req.getCloudSiteId(), req.getTenantId(), stackId, success);
145 DeleteNetworkResponse deleteResponse =
146 new DeleteNetworkResponse(req.getNetworkId(), true, req.getMessageId());
147 response = deleteResponse.toXmlString();
148 } else if ("updateNetworkRequest".equals(requestType.get())) {
149 UpdateNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), UpdateNetworkRequest.class);
150 pollUpdateResource(req.getCloudSiteId(), req.getTenantId(), externalTask, success);
151 UpdateNetworkResponse updateResponse =
152 new UpdateNetworkResponse(req.getNetworkId(), null, null, req.getMessageId());
153 response = updateResponse.toXmlString();
156 } catch (Exception e) {
157 logger.error("Error during External Task Poll Service", e);
158 errorMessage = e.toString();
159 variables.put("openstackAdapterErrorMessage", errorMessage);
162 variables.put("WorkflowResponse", response);
163 variables.put("OpenstackPollSuccess", success.booleanValue());
164 if (success.isTrue()) {
165 externalTaskService.complete(externalTask, variables);
166 logger.debug("The External Task Id: {} Successful", externalTask.getId());
168 if (externalTask.getRetries() == null) {
169 logger.debug("The External Task Id: {} Failed, Setting Retries to Default Start Value: {}",
170 externalTask.getId(), getRetrySequence().length);
171 externalTaskService.handleFailure(externalTask, "errorMessage", "errorDetails",
172 getRetrySequence().length, 10000);
173 } else if (externalTask.getRetries() != null && externalTask.getRetries() - 1 == 0) {
174 logger.debug("The External Task Id: {} Failed, All Retries Exhausted", externalTask.getId());
175 externalTaskService.complete(externalTask, variables);
177 logger.debug("The External Task Id: {} Failed, Decrementing Retries: {} , Retry Delay: {}",
178 externalTask.getId(), externalTask.getRetries() - 1,
179 calculateRetryDelay(externalTask.getRetries()));
180 externalTaskService.handleFailure(externalTask, "errorMessage", "errorDetails",
181 externalTask.getRetries() - 1, calculateRetryDelay(externalTask.getRetries()));
186 private String determineCreateVolumeGroupStatus(String xmlRequest, ExternalTask externalTask,
187 MutableBoolean success) throws MsoException {
188 CreateVolumeGroupRequest req = JAXB.unmarshal(new StringReader(xmlRequest), CreateVolumeGroupRequest.class);
189 boolean isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
191 boolean pollRollbackStatus = externalTask.getVariable("PollRollbackStatus");
192 String stackId = externalTask.getVariable("stackId");
193 if (pollRollbackStatus) {
194 logger.debug("Executing External Task Poll Service for Rollback Create Volume Group");
195 pollDeleteResource(118, req.getCloudSiteId(), req.getTenantId(), stackId, success);
196 DeleteVolumeGroupResponse deleteResponse = new DeleteVolumeGroupResponse(true, req.getMessageId());
197 return deleteResponse.toXmlString();
199 int timeoutMinutes = msoHeatUtils.getVfHeatTimeoutValue(req.getModelCustomizationUuid(), true);
201 pollCreateResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
202 VolumeGroupRollback rb =
203 new VolumeGroupRollback(req.getVolumeGroupId(), stackId, true, req.getTenantId(),
204 req.getCloudOwner(), req.getCloudSiteId(), req.getMsoRequest(), req.getMessageId());
205 CreateVolumeGroupResponse createResponse = new CreateVolumeGroupResponse(req.getVolumeGroupId(),
206 stackId, true, vnfAdapterImpl.copyStringOutputs(stack.getOutputs()), rb, req.getMessageId());
207 return createResponse.toXmlString();
215 private String determineCreateVfModuleStatus(String xmlRequest, ExternalTask externalTask, MutableBoolean success)
216 throws MsoException {
217 CreateVfModuleRequest req = JAXB.unmarshal(new StringReader(xmlRequest), CreateVfModuleRequest.class);
218 boolean isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
219 String stackId = externalTask.getVariable("stackId");
221 boolean pollRollbackStatus = externalTask.getVariable("PollRollbackStatus");
222 int timeoutMinutes = msoHeatUtils.getVfHeatTimeoutValue(req.getModelCustomizationUuid(), false);
223 if (pollRollbackStatus) {
224 logger.debug("Executing External Task Poll Service for Rollback Create Vf Module");
226 pollDeleteResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
227 DeleteVfModuleResponse deleteResponse = new DeleteVfModuleResponse(req.getVnfId(), req.getVfModuleId(),
228 Boolean.TRUE, req.getMessageId(), vnfAdapterImpl.copyStringOutputs(stack.getOutputs()));
229 return deleteResponse.toXmlString();
231 logger.debug("Executing External Task Poll Service for Create Vf Module");
233 pollCreateResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
234 VfModuleRollback modRollback = new VfModuleRollback(buildVnfRollback(req, stackId, isMulticloud),
235 req.getVfModuleId(), stackId, req.getMessageId());
236 CreateVfModuleResponse createResponse =
237 new CreateVfModuleResponse(req.getVnfId(), req.getVfModuleId(), stackId, Boolean.TRUE,
238 vnfAdapterImpl.copyStringOutputs(stack.getOutputs()), modRollback, req.getMessageId());
239 return createResponse.toXmlString();
247 private String determineCreateNetworkStatus(String xmlRequest, ExternalTask externalTask, MutableBoolean success)
248 throws MsoException {
249 CreateNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), CreateNetworkRequest.class);
250 String stackId = externalTask.getVariable("stackId");
251 boolean pollRollbackStatus = externalTask.getVariable("PollRollbackStatus");
253 msoHeatUtils.getNetworkHeatTimeoutValue(req.getModelCustomizationUuid(), req.getNetworkType());
254 if (pollRollbackStatus) {
255 logger.debug("Executing External Task Poll Service for Rollback Create Network");
256 pollDeleteResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
257 DeleteNetworkResponse response = new DeleteNetworkResponse(req.getNetworkId(), true, req.getMessageId());
258 return response.toXmlString();
260 logger.debug("Executing External Task Poll Service for Create Network");
261 boolean os3Nw = externalTask.getVariable("os3Nw");
263 pollCreateResource(timeoutMinutes, req.getCloudSiteId(), req.getTenantId(), stackId, success);
264 String networkFqdn = "";
265 String neutronNetworkId = "";
266 Map<String, String> subnetMap = new HashMap<>();
267 if (stack.getOutputs() != null) {
268 networkFqdn = (String) stack.getOutputs().get("network_fqdn");
269 neutronNetworkId = (String) stack.getOutputs().get("network_id");
270 subnetMap = networkAdapterImpl.buildSubnetMap(stack.getOutputs(), req.getSubnets(), os3Nw);
272 CreateNetworkResponse response = new CreateNetworkResponse(req.getNetworkId(), neutronNetworkId, stackId,
273 networkFqdn, true, subnetMap, buildNetworkRollback(req, stackId), req.getMessageId());
274 return response.toXmlString();
279 private StackInfo pollCreateResource(int pollingTimeout, String cloudSiteId, String tenantId, String stackId,
280 MutableBoolean success) throws MsoException {
281 Stack currentStack = createCurrentStack(stackId);
282 Stack stack = msoHeatUtils.pollStackForStatus(pollingTimeout, currentStack, "CREATE_IN_PROGRESS", cloudSiteId,
284 msoHeatUtils.postProcessStackCreate(stack, false, 0, false, cloudSiteId, tenantId, null);
286 return new StackInfoMapper(stack).map();
289 private StackInfo pollDeleteResource(int pollingTimeout, String cloudSiteId, String tenantId, String stackId,
290 MutableBoolean success) throws MsoException {
291 Stack currentStack = createCurrentStack(stackId);
292 Stack stack = msoHeatUtils.pollStackForStatus(pollingTimeout, currentStack, "DELETE_IN_PROGRESS", cloudSiteId,
294 if (stack != null) { // if stack is null it was not found and no need to do post process
295 msoHeatUtils.postProcessStackDelete(stack);
298 return new StackInfoMapper(stack).map();
301 private void pollUpdateResource(String cloudSiteId, String tenantId, ExternalTask externalTask,
302 MutableBoolean success) throws MsoException {
303 Stack currentStack = createCurrentStack(externalTask.getVariable("stackId"));
305 msoHeatUtils.pollStackForStatus(1, currentStack, "UPDATE_IN_PROGRESS", cloudSiteId, tenantId, false);
306 msoHeatUtils.postProcessStackUpdate(stack);
310 protected Optional<String> findRequestType(String xmlString) {
312 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
313 DocumentBuilder builder = factory.newDocumentBuilder();
314 org.w3c.dom.Document doc;
315 doc = builder.parse(new ByteArrayInputStream(xmlString.getBytes("UTF-8")));
316 return Optional.of(doc.getDocumentElement().getNodeName());
317 } catch (Exception e) {
318 logger.error("Error Finding Request Type", e);
319 return Optional.empty();
323 private Stack createCurrentStack(String canonicalStackId) {
324 Stack currentStack = new Stack();
325 String stackName = canonicalStackId;
326 if (canonicalStackId.contains("/")) {
327 String[] stacks = canonicalStackId.split("/");
328 stackName = stacks[0];
329 currentStack.setId(stacks[1]);
331 currentStack.setStackName(stackName);
335 private VnfRollback buildVnfRollback(CreateVfModuleRequest req, String stackId, boolean isMulticloud) {
336 VnfRollback vfRollback = new VnfRollback();
337 vfRollback.setCloudSiteId(req.getCloudSiteId());
338 vfRollback.setCloudOwner(req.getCloudOwner());
339 vfRollback.setTenantId(req.getTenantId());
340 vfRollback.setMsoRequest(req.getMsoRequest());
341 vfRollback.setRequestType(req.getRequestType());
342 vfRollback.setVolumeGroupHeatStackId(req.getVolumeGroupStackId());
343 vfRollback.setBaseGroupHeatStackId(req.getBaseVfModuleStackId());
344 vfRollback.setIsBase(false);
345 vfRollback.setModelCustomizationUuid(req.getModelCustomizationUuid());
346 vfRollback.setVnfId(stackId);
347 vfRollback.setVnfCreated(true);
349 vfRollback.setMode("CFY");
354 private NetworkRollback buildNetworkRollback(CreateNetworkRequest req, String stackId) {
355 NetworkRollback networkRollback = new NetworkRollback();
356 networkRollback.setCloudId(req.getCloudSiteId());
357 networkRollback.setTenantId(req.getTenantId());
358 networkRollback.setMsoRequest(req.getMsoRequest());
359 networkRollback.setModelCustomizationUuid(req.getModelCustomizationUuid());
360 networkRollback.setNetworkStackId(stackId);
361 networkRollback.setNetworkCreated(true);
362 networkRollback.setNetworkType(req.getNetworkType());
364 return networkRollback;